Получение повышения:: общий 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)) Я создал второй общий указатель на мой объект это в конечном итоге приведет к двойному удалению.

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

6 76

6 ответов:

можно получить из enable_shared_from_this и затем вы можете использовать "shared_from_this()" вместо "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() вместо этого. Это гарантирует, что объект не будет освобожден.

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

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

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

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


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

С C++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';

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

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

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