Получаем повышение::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))
Я создам второй общий указатель на мой объект, который в конечном итоге приведет к двойному удалению.
Это подводит меня к моему вопросу: существует ли какой-либо стандартный шаблон для получения копии существующего общего указателя, который, как вы знаете, существует внутри метода одного из этих объектов? Является ли использование навязчивого подсчета ссылок моим единственным вариантом здесь?
6 ответов
Вы можете наследовать от 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
}
Это хорошая идея, когда порождает потоки из функции-члена, чтобы повысить:: связать с shared_from_this () вместо этого. Это гарантирует, что объект не будет освобожден.
Просто используйте необработанный указатель для вашего параметра функции вместо shared_ptr. Цель интеллектуального указателя - управлять временем жизни объекта, но время жизни объекта уже гарантировано правилами области видимости C++: он будет существовать, по крайней мере, до конца вашей функции. То есть вызывающий код не может удалить объект до того, как ваша функция вернется; таким образом, безопасность "тупого" указателя гарантируется, если вы не пытаетесь удалить объект внутри вашей функции.
Единственный раз, когда вам нужно передать shared_ptr в функцию, это когда вы хотите передать владение объектом функции или хотите, чтобы функция сделала копию указателя.
boost имеет решение для этого варианта использования, проверьте enable_shared_from_this
Вы действительно делаете больше общих копий pFoo внутри бара? Если вы не делаете ничего сумасшедшего внутри, просто сделайте это:
void bar(Foo &foo)
{
// ...
}
С С ++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 вокруг этого объекта (в теле функции). Это сработает, чтобы принять "this" или вообще любой объект, выделенный в куче.
- Поделитесь указателем (не принадлежите ему) на передаваемый объект. В этом случае вы вообще не хотите использовать scoped_ptr, так как не хотите удалять объект в конце своей функции. В этом случае, что вам теоретически нужно, так это shared_ptr (я видел, что в другом месте он называется connected_ptr). В библиотеке boost есть версия shared_ptr, и это также рекомендуется в книге Скотта Мейерса "Эффективный C++" (пункт 18 в 3-м издании).
Изменить: К сожалению, я немного неправильно понял вопрос, и теперь я вижу, что этот ответ не совсем отвечает на вопрос. Я все равно оставлю это на всякий случай, если это может быть полезно для тех, кто работает над подобным кодом.