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

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

"Используется ли здесь навязчивый подсчет ссылок - мой единственный вариант?" Что не так с этой опцией?

curiousguy 07.10.2011 18:31

Может ничего. Зависит от ваших обстоятельств. Это действительно увеличивает ваши объекты и может не работать там, где у вас нет контроля над классами, для которых вы храните смарт-указатели.

Joe Ludwig 08.10.2011 03:15

enable_shared_from_this теперь в std::. Посмотри на мой ответ.

Johan Lundberg 25.12.2012 23:02
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
77
3
36 723
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

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

Ответ принят как подходящий

Вы можете унаследовать от enable_shared_from_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. Это гарантирует, что объект не будет выпущен.

f () похож на ".Copy ()", и это также неглубокая копия.

Anton Andreev 10.02.2012 17:39

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


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

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

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

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

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

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

Согласовано. Много раз вы можете использовать foo (const Object * object_ptr) {} foo (obj.get ()); где obj - это boost :: shared_ptr <Object>. Поищите в Интернете Херб Саттер - другой автор статей, у которого есть отличная информация об этой и подобных проблемах.

bn. 13.08.2009 08:28

Это немного не по делу, но ... Если вы можете использовать указатель, то (скорее всего) вы можете использовать ссылку, что лучше IMO.

denis-bu 26.12.2013 23:27

@ denis-bu, кроме случаев, когда возможен указатель NULL. Но вы правильно подметили.

Mark Ransom 26.12.2013 23:56

Очевидно, на 12 лет позже этого, но я не понимаю этого ответа. Тип аргумента bar отличается от необработанного указателя. Без «явного» ключевого слова, которое сделало бы передачу «this» неудачной для компиляции, не стал бы компилятор попытаться построить shared_ptr из необработанного указателя, создав в процессе блок счетчика ссылок, установив счетчик ссылок в 1, а затем выйти из бара, уменьшить счетчик ссылок до 0 и попытаться удалить «это»?

Foster Boondoggle 19.08.2020 17:53

@FosterBoondoggle, я предложил изменить тип параметра bar на необработанный указатель.

Mark Ransom 19.08.2020 23:12

В 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';

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