Я широко использую 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 теперь в std::. Посмотри на мой ответ.





У 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 ()", и это также неглубокая копия.
Вы действительно делаете больше общих копий pFoo внутри бара? Если внутри вы не делаете ничего сумасшедшего, просто сделайте следующее:
void bar(Foo &foo)
{
// ...
}
Функция, принимающая указатель, хочет выполнить одно из двух действий:
Редактировать: К сожалению, я немного неправильно понял вопрос, и теперь я вижу, что этот ответ не совсем отвечает на вопрос. Я все равно оставлю это, на случай, если это может быть полезно для тех, кто работает над аналогичным кодом.
Просто используйте необработанный указатель для параметра функции вместо shared_ptr. Назначение интеллектуального указателя - контролировать время жизни объекта, но время жизни объекта уже гарантируется правилами области видимости C++: он будет существовать, по крайней мере, до конца вашей функции. То есть вызывающий код не может удалить объект до того, как ваша функция вернется; таким образом, безопасность «тупого» указателя гарантируется, пока вы не пытаетесь удалить объект внутри своей функции.
Единственный раз, когда вам нужно передать shared_ptr в функцию, - это когда вы хотите передать право собственности на объект функции или хотите, чтобы функция сделала копию указателя.
Согласовано. Много раз вы можете использовать foo (const Object * object_ptr) {} foo (obj.get ()); где obj - это boost :: shared_ptr <Object>. Поищите в Интернете Херб Саттер - другой автор статей, у которого есть отличная информация об этой и подобных проблемах.
Это немного не по делу, но ... Если вы можете использовать указатель, то (скорее всего) вы можете использовать ссылку, что лучше IMO.
@ denis-bu, кроме случаев, когда возможен указатель NULL. Но вы правильно подметили.
Очевидно, на 12 лет позже этого, но я не понимаю этого ответа. Тип аргумента bar отличается от необработанного указателя. Без «явного» ключевого слова, которое сделало бы передачу «this» неудачной для компиляции, не стал бы компилятор попытаться построить shared_ptr из необработанного указателя, создав в процессе блок счетчика ссылок, установив счетчик ссылок в 1, а затем выйти из бара, уменьшить счетчик ссылок до 0 и попытаться удалить «это»?
@FosterBoondoggle, я предложил изменить тип параметра bar на необработанный указатель.
В 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';
"Используется ли здесь навязчивый подсчет ссылок - мой единственный вариант?" Что не так с этой опцией?