Создать 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.