Вопрос

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

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

Это было полезно?

Решение

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

Пример по ссылке:

#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() вместо this .Это гарантирует, что объект не будет освобожден.

Другие советы

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

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

у boost есть решение для этого варианта использования, проверьте enable_shared_from_this включить общий доступ из_this

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


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-м издании).

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top