Идиоматическое использование std:: auto_ptr или использование shared_ptr?
Теперь, когда shared_ptr
находится в tr1, что, по-вашему, должно произойти с использованием std::auto_ptr
? Они оба имеют разные варианты использования, но все варианты использования auto_ptr
могут быть решены с помощью shared_ptr
. Вы откажетесь от auto_ptr
или продолжите использовать его в тех случаях, когда вы хотите явно выразить, что только один класс имеет право собственности в любой точке?
Я считаю, что использование auto_ptr
может добавить ясность в код, точно добавив нюанс и указание на дизайн кода, но, с другой стороны, он добавляет еще одну тонкую проблему при обучении новых программистов: им нужно понимать умные указатели и тонкие детали того, как они работают. Когда вы используете только один умный указатель повсюду, вы можете просто установить правило "обернуть все указатели в shared_ptr
" и сделать с ним.
Что вы берете на себя?
Ответы
Ответ 1
Чтобы обеспечить немного больше боеприпасов для лагеря "избегать std::auto_ptr
": auto_ptr
устаревает в следующем стандарте (С++ 0x). Я считаю, что это один достаточно хороший боеприпас для любого аргумента, чтобы использовать что-то еще.
Однако, как отметил Конрад Рудольф, замена по умолчанию для auto_ptr
должна быть boost::scoped_ptr
. Семантика scoped_ptr
более близка к семантике auto_ptr
и предназначена для аналогичного использования. Следующий стандарт С++ 09 будет иметь что-то подобное с именем unique_ptr.
Однако использование shared_ptr
в любом месте, где используется scoped_ptr
, ничего не сломает, оно просто добавит очень незначительную часть неэффективности для обработки счетчика ссылок, если объект никогда не будет использоваться совместно. Поэтому для частных указателей-членов, которые никогда не будут переданы другому объекту, используйте scoped_ptr
. Если указатель будет передан кому-то еще (это включает использование их в контейнерах или если все, что вы хотите сделать, это передача права собственности, а не сохранение или обмен ими) - используйте shared_ptr
.
Ответ 2
auto_ptr тоже хорош в подписях. Когда функция принимает значение auto_ptr<T>
по значению, это означает, что она будет потреблять T
. Если функция возвращает auto_ptr<T>
, она ясно указывает, что она отказывается от права собственности. Это может сообщить ваши намерения о жизни.
С другой стороны, использование scoped_ptr<T>
подразумевает, что вы не хотите заботиться о времени жизни T
. Это также означает, что вы можете использовать его в большем количестве мест. Оба умных указателя являются допустимыми вариантами, вы, безусловно, можете иметь как в одной программе.
Ответ 3
"Использовать shared_ptr
везде" является хорошим стандартом по умолчанию и, безусловно, хорошей отправной точкой для обучения людей ответственному использованию интеллектуальных указателей. Однако это не всегда лучший выбор.
Если вам не требуется совместное владение, shared_ptr
является излишним: ему нужно выделить отдельный блок памяти для счетчика ссылок, что может повлиять на производительность, и оно менее четкое по документации.
Лично я использую std::auto_ptr
во многих местах, где также будет boost::scoped_ptr
: например. удерживая объект, выделенный в кучу, до того, как собственность передана в другом месте, где могут быть брошены промежуточные операции.
С++ 0x будет иметь std::unique_ptr
, чтобы дополнить std::shared_ptr
лучшей альтернативой std::auto_ptr
. Когда он станет широко доступным, я начну использовать его.
Ответ 4
Я считаю, что наилучшей практикой является замена всех видов использования std::auto_ptr
на boost::scoped_ptr
, если std::tr1::shared_ptr
не соответствует требованиям лучше, если вы не против использования Boost. С другой стороны, было очевидно, что scoped_ptr
не был включен в TR1.
Ответ 5
Я считаю, что "обернуть все указатели в shared_ptr
" действительно должно быть режимом по умолчанию и является подходящим советом для предоставления вашим младшим кодерам. Тем не менее, в специальных случаях, которые вы упомянули, auto_ptr
действительно более уместно, и его использование следует поощрять при таких обстоятельствах.