Получение boost:: shared_ptr для этого

Я использую boost:shared_ptr в моем коде. Фактически, большинство объектов, которые выделены в куче, удерживаются символом shared_ptr. К сожалению, это означает, что я не могу передать this в любую функцию, которая принимает shared_ptr. Рассмотрим этот код:

void bar(boost::shared_ptr<Foo> pFoo)
{
    ...
}

void Foo::someFunction()
{
    bar(this);
}

Здесь есть две проблемы. Во-первых, это не будет компилироваться, потому что конструктор T * для shared_ptr является явным. Во-вторых, если я заставляю его строить с помощью bar(boost::shared_ptr<Foo>(this)), я создам второй общий указатель на мой объект, который в итоге приведет к двойному удалению.

Это подводит меня к моему вопросу: существует ли стандартный шаблон для получения копии существующего общего указателя, который, как вы знаете, существует внутри метода на одном из этих объектов? Использует ли интрузивный счет, ссылаясь на мой единственный вариант здесь?

Ответ 1

Вы можете получить enable_shared_from_this, а затем вместо "this" вы можете использовать "shared_from_this()", чтобы создать общий указатель на ваш собственный объект.

Пример в ссылке:

#include <boost/enable_shared_from_this.hpp>

class Y: public boost::enable_shared_from_this<Y>
{
public:

    shared_ptr<Y> f()
    {
        return shared_from_this();
    }
}

int main()
{
    shared_ptr<Y> p(new Y);
    shared_ptr<Y> q = p->f();
    assert(p == q);
    assert(!(p < q || q < p)); // p and q must share ownership
}

Это хорошая идея, когда порождает потоки из функции-члена для boost:: bind вместо shared_from_this(). Это гарантирует, что объект не будет выпущен.

Ответ 2

Просто используйте необработанный указатель для параметра функции вместо shared_ptr. Цель умного указателя - управлять временем жизни объекта, но время жизни объекта уже гарантировано правилами С++: оно будет существовать, по крайней мере, до конца вашей функции. То есть вызывающий код не может удалить объект до того, как ваша функция вернется; таким образом, безопасность "немого" указателя гарантируется, если вы не пытаетесь удалить объект внутри своей функции.

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

Ответ 3

boost имеет решение для этого варианта использования, проверьте enable_shared_from_this

Ответ 4

Вы действительно делаете более общие копии внутренней панели pFoo? Если вы не делаете ничего сумасшедшего внутри, просто сделайте следующее:


void bar(Foo &foo)
{
    // ...
}

Ответ 5

С С++ 11 shared_ptr и enable_shared_from_this теперь находится в стандартной библиотеке. Последнее, как следует из названия, для этого случая точно.

http://en.cppreference.com/w/cpp/memory/shared_ptr

http://en.cppreference.com/w/cpp/memory/enable_shared_from_this

Примеры баз данных по ссылкам выше:

struct Good: std::enable_shared_from_this<Good>{
    std::shared_ptr<Good> getptr() {
        return shared_from_this();
    }
};

использование:

std::shared_ptr<Good> gp1(new Good);
std::shared_ptr<Good> gp2 = gp1->getptr();
std::cout << "gp2.use_count() = " << gp2.use_count() << '\n';

Ответ 6

Функция, принимающая указатель, хочет выполнить одно из двух действий:

  • Собственный объект передается и удаляется, когда он выходит из области видимости. В этом случае вы можете просто принять X * и немедленно обернуть scoped_ptr вокруг этого объекта (в теле функции). Это будет работать, чтобы принять "this" или, в общем, любой выделенный кучей объект.
  • Поделитесь указателем (не владейте им) с передаваемым объектом. В этом случае вы вообще не хотите использовать scoped_ptr, так как вы не хотите удалять объект в конце вашей функции. В этом случае то, что вы теоретически хотите, является shared_ptr (я видел, что он называется связанным_ptr в другом месте). Библиотека ускорения версия shared_ptr, и это также рекомендуется в "Эффективной книге С++" Скотта Майерса (пункт 18 в 3-м издании).

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