Это хорошая практика, чтобы передать scoped_ptr по ссылке (от одного метода к другому внутри класса)?

Или, если мне нужно сделать это, то я должен просто использовать shared_ptr?

3 ответа

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

В общем, есть умные указатели для управления владением объектами, так что вот краткий обзор:

  • boost::scoped_ptr ограничивает время жизни охраняемого объекта для окружающей области, есть только один владелец.
  • С std::auto_ptr есть также только один владелец за раз, но он позволяет передавать владение через присваивание (как параметр функции или возвращаемое значение.)
  • boost::shared_ptr поддерживает общее владение посредством подсчета ссылок, охраняемый объект уничтожается только тогда, когда счетчик ссылок становится равным нулю. Это самый универсальный интеллектуальный указатель, но также и самый дорогой, поскольку он переносит незначительные накладные расходы (счетчик ссылок поддерживается с помощью атомарных операций, которые довольно дороги.) Также существует возможность циклических зависимостей.
  • boost::weak_ptr не обладающий смарт-указатель, который может быть обновлен до boost::shared_ptr во время выполнения с проверкой, что охраняемый объект все еще жив.

Есть также варианты массива, такие как boost::shared_array так как C++ имеет отдельные функции освобождения для одного и нескольких объектов (operator delete против operator delete[].)

Интеллектуальные указатели поддерживают идиому Resource Acquisition Is Initialization, или RAII, которая является способом обеспечения гарантий безопасности исключений.

Да, вы можете передать его по ссылке.

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

void foo(const boost::scoped_ptr<Object>& o)
{
     o->foobar();
}

void bar(const Object& o)
{
     o.foobar();
}

Разница в том, что в первом случае вы связали функцию с определенным типом интеллектуального указателя.

Object o;
boost::scoped_ptr<Object> scoped(new Object);
boost::shared_ptr<Object> shared(new Object);

foo(o);  //no
foo(scoped); //OK
foo(shared); //no

bar(o);  //OK
bar(*scoped); //OK
bar(*shared); //OK

Как правило, я бы только передать scoped_ptr, если намерение сделать что-то с scoped_ptr сам экземпляр (например, освободить или сбросить ресурс). Аналогично для shared_ptr (например, функция хочет поделиться ресурсом с другими общими указателями).

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

Реальное преимущество заключается в том, что вы экономите на стоимости обновления счетчика ссылок таким способом. Быстро прочитав вики http://en.wikipedia.org/wiki/Reference_counting вы поймете, что постоянное выполнение +1 / -1 (предположительно атомарных) операций со счетчиком ссылок может разрушить ваш кеш.

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