У меня есть существующая переменная, например
int a = 3;
Как я могу создать boost::shared_ptr
до a
? Например:
boost::shared_ptr< int > a_ptr = &a; // this doesn't work
У меня есть существующая переменная, например
int a = 3;
Как я могу создать boost::shared_ptr
до a
? Например:
boost::shared_ptr< int > a_ptr = &a; // this doesn't work
хотя вы должны поместить переменную в управляемый указатель на ее создание, чтобы сделать это из существующего указателя.
int *a=new int;
boost::shared_ptr<int> a_ptr(a);
Если по какой-либо причине функция принимает 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 находится в стандарте С++ 11, если вы можете это использовать. Вы можете использовать auto в сочетании с make_shared, как отмечает Herb Sutter, в разговоре о сборке.
#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
для С++ 11:
auto noop_deleter = [](int*) {};
Версия С++ 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.