Создать boost::shared_ptr для существующей переменной

У меня есть переменная, например,

int a = 3;

Как я могу теперь создать boost::shared_ptr в a? Например:

boost::shared_ptr< int > a_ptr = &a; // this doesn't work

4 ответа

Решение

Хотя вы должны поместить переменную в управляемый указатель при ее создании, чтобы сделать это из существующего указателя.

int *a=new int;
boost::shared_ptr<int> a_ptr(a);

Тем не менее, вы определенно не хотите помещать переменные стека в shared_ptr ПЛОХИЕ ВЕЩИ БУДУТ

Если по какой-то причине функция принимает shared_ptr и у вас есть только стек, то лучше сделать это:

int a=9;
boost::shared_ptr<int> a_ptr=boost::make_shared(a);

Посмотреть здесь:

http://www.boost.org/doc/libs/1_43_0/libs/smart_ptr/make_shared.html

Также стоит отметить, что shared_ptr соответствует стандарту C++11, если вы можете его использовать. Вы можете использовать auto в сочетании с make_shared, как отмечает Херб Саттер в сборке.

#include <memory>

int a=9;
auto a_ptr=std::make_shared(9);

Во-первых, у вас есть ошибка, потому что shared_ptrне будет автоматически конвертировать из указателя соответствующего типа. Вы должны четко указать, что вы хотите сделать:

int a = 3;
::boost::shared_ptr< int > a_ptr(&a); // DO NOT DO THIS!

У вас есть еще одна проблема. Представьте себе эффект этого кода:

int a = 3;
delete &a;

В первом примере, который я привел, это неизбежно произойдет, даже если оно не будет таким прямым. shared_ptrВся причина существования заключается в удалении вещей, когда все указатели на него исчезают. Это, конечно, вызовет все виды странного поведения.

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

Делать то, что можно удалить:

Плюсы:

  • Просто и легко.
  • Вам не нужно беспокоиться о времени жизни объекта.

Минусы:

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

Как это сделать:

::boost::shared_ptr<int> a_ptr(::boost::make_shared(a));

Это довольно похоже на (и это также будет работать):

::boost::shared_ptr<int> a_ptr(new int(a));

Но это немного более эффективно. ::boost::make_shared делает некоторую магию, чтобы выделить счетчик ссылок и объект в непрерывной памяти, что экономит на вызовах распределителю и улучшает локальность ссылок.

Делать так, чтобы shared_ptr на самом деле не удаляет то, на что он указывает:

Плюсы:

  • Быстрее, хотя все еще включает выделение кучи для подсчета ссылок
  • Непосредственно решает проблему (вещь, на которую вы указываете, не может быть удалена).
  • shared_ptr относится к a, поэтому, если вы измените его значение, вещи, которые обращаются к нему через указатель, увидят новое значение.

Минусы:

  • Требуется знать немного больше о том, как shared_ptr работает, что означает, что люди, читающие ваш код, тоже должны это знать.
  • Если вещь, на которую вы указываете, выходит за рамки shared_ptrЭто значит, что эти указатели становятся висящими, и это плохо.
  • Предыдущий пункт делает это очень рискованным решением. Я бы вообще этого избегал.

Как это сделать:

Где-то за пределами функции (возможно, в анонимном пространстве имен):

void do_nothing_deleter(int *)
{
    return;
}

И тогда в функции:

int a = 3;
::boost::shared_ptr a_ptr(&a, do_nothing_deleter);

То, что вы написали, не сработает, потому что конструктор shared_ptr вы ищете это explicitтак что вам нужно написать так

boost::shared_ptr<int> a_ptr(&a); // Don't do that!

Однако проблема в том, что delete будет вызываться на сохраненном значении a_ptr, Так как в вашем примере a имеет автоматическое время хранения, это очень плохо. Итак, мы также передаем пользовательский удалитель:

boost::shared_ptr<int> a_ptr(&a, noop_deleter);

Реализация noop_deleter для C++11:

auto noop_deleter = [](int*) {};

Версия C++03:

// Can't be put in local scope
struct {
    void
    operator()(int*) const
    {}
} noop_deleter;

Вы не можете создать boost:: shared_ptr для существующей переменной. Элементы, хранящиеся в boost:: shared_ptr, сохраняются при создании.

Однако вы можете сделать boost:: shared_ptr, который является копией существующей переменной.

Например

int a = 3; // Existing variable
boost::shared_ptr<int> aCopy = boost::make_shared<int>(a); //Create copy with value of a

Обратите внимание, что вам нужно будет включить <boost/make_shared.hpp> для make_shared.

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