Увеличить make_shared без аргумента шаблона

Я пытаюсь передать указатель на переменную стека в функцию (я не контролирую), которая принимает только boost::shared_ptr,

Согласно этому ответу, используя boost::make_shared это путь Чтобы проверить эту функциональность, я написал это:

#include <iostream>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>

int main(int argc, char const *argv[])
{
    int i = 10;
    boost::shared_ptr<int> int_ptr = boost::make_shared(i); // doesn't work
    some_function(int_ptr); // this function takes only shared_ptr
    return 0;
}

Но выдает следующую ошибку:

error: no matching function for call to ‘make_shared(int&)’
boost::shared_ptr<int> int_ptr = boost::make_shared(i);
                                                     ^

Если я добавлю аргумент шаблона так, как он работает, но какова причина этого?

boost::shared_ptr<int> int_ptr = boost::make_shared<int>(i);

Спасибо!

2 ответа

Решение

Учитывая boost::make_shared<T> шаблон:

namespace boost {
    template<typename T, typename Arg1>
      shared_ptr<T> make_shared( Arg1 const & arg1 );
}

Механизм шаблона может определить тип параметра. arg1, Потому что он "видит" тип аргумента i (который int). Тем не менее, он не может вывести тип возвращаемого значения T, Не знает тип T из boost::shared_ptr<T> вы будете назначать (т.е. он не имеет возможности узнать тип int_ptr.)

boost::shared_ptr<T> использует разные типы для аргумента (Arg1) и вернуться (T), чтобы позволить вам создавать общие указатели из аргументов, отличных от типа указателя. Например, double в int:

double d = 10.0;
std::shared_ptr<int> int_ptr = std::make_shared<int>(d);

Если вы хотите создать общие указатели, тип которых совпадает с аргументом, вы можете написать оболочку:

template<typename T>
boost::shared_ptr<T> my_make_shared(T const & arg) {
    return boost::make_shared<T>(arg);
}

Но имейте в виду, что пока это работает

int i = 10.0;
std::shared_ptr<int> int_ptr = my_make_shared(i); // OK

Неявное преобразование типов не делает:

double d = 10.0;
std::shared_ptr<int> int_ptr = my_make_shared(d); // ERROR

Надеюсь, поможет!

Хотя в ответе Гильерме Феррейры подробно рассматривается вывод шаблонных аргументов (и в этом отношении он является правильным), я считаю, что это не тот ответ, который вы ищете.

Я пытаюсь передать указатель на переменную стека в функцию (я не контролирую), которая принимает только boost::shared_ptr.

shared_ptr означает совместное владение указанным объектом. Если функция, которую вы пытаетесь вызвать, сохраняет указатель в некоторых своих структурах данных, например в контейнере, и затем возвращает его, указатель станет зависать, как только значение в стеке будет уничтожено, несмотря на то, что shared_ptr все еще держит ссылку. Чтобы сделать то, что вы хотите, вы должны быть абсолютно уверены, что функция нигде не сохраняет указатель и может использовать его только во время этого одного вызова.

При условии, что это условие выполнено, вы можете создать shared_ptr указывая на значение в стеке, но вы не можете использовать make_shared для этого. make_shared выделяет новый объект в куче вместе со счетчиком ссылок для него и инициализирует его аргументами, переданными в вызов функции. Возвращенный shared_ptr указывает на этот новый объект, а не на объект в стеке.

void foo()
{
    int n = 10;
    boost::shared_ptr< int > pn = boost::make_shared< int >(n);

    assert(*pn == 10); // succeeds
    assert(pn.get() == &n); // fails

    bar(pn);
}

Это подразумевает, что модификации bar делает на острие int не отражаются на n,

Для того, чтобы создать shared_ptr к существующему объекту, вы должны использовать его конструктор напрямую. Кроме того, поскольку время жизни объекта контролируется стеком, вы должны запретить shared_ptr от уничтожения объекта. Это можно сделать, указав no-op delete shared_ptr строительство.

void foo()
{
    int n = 10;
    boost::shared_ptr< int > pn(&n, boost::null_deleter());

    assert(*pn == 10); // succeeds
    assert(pn.get() == &n); // succeeds

    bar(pn);
}

Обратите внимание, однако, что этот код по-прежнему выделяет кучу памяти для счетчика ссылок shared_ptr использует, так что вы не выиграли ни одного представления.

Другие вопросы по тегам