Подтвердить что ты не робот

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

У меня есть существующая переменная, например

int a = 3;

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

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

Ответ 1

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

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 находится в стандарте С++ 11, если вы можете это использовать. Вы можете использовать auto в сочетании с make_shared, как отмечает Herb Sutter, в разговоре о сборке.

#include <memory>

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

Ответ 2

Сначала у вас есть ошибка, потому что 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);

Ответ 3

То, что вы написали, не будет работать, потому что конструктор 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;

Ответ 4

Вы не можете создать 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.