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

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

Ответы [ 3 ]

13 голосов
/ 21 марта 2010

Безопасно передавать 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[].)

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

11 голосов
/ 21 марта 2010

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

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

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 (например, функция хочет поделиться ресурсом с другими общими указателями).

0 голосов
/ 30 июля 2011

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

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

...