Использование умных указателей - PullRequest
3 голосов
/ 29 декабря 2010

У меня есть проект, и я хочу улучшить использование умных указателей.

Основная идея - использовать их при возврате нового объекта из функции. Вопрос в том, какой умный указатель использовать? auto_ptr или shared_ptr от boost? Как я знаю, auto_ptr медленнее, но может возвращаться к «чистому» указателю.

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

Ответы [ 5 ]

12 голосов
/ 29 декабря 2010

Что заставляет вас думать, что auto_ptr медленнее, чем shared_ptr? Обычно я ожидаю, что обратное будет правдой, поскольку shared_ptr необходимо обновить счетчик ссылок.

Что касается того, что вы должны использовать, разные умные указатели подразумевают разную семантику владения. Право собственности подразумевает ответственность за удаление объекта, когда он больше не нужен.

  • Необработанный указатель подразумевает нет собственности ; программа, которая правильно использует умные указатели, может по-прежнему использовать необработанные указатели во многих местах, где владение не предусмотрено (например, если вам нужно передать необязательную ссылку на объект в функцию, вы часто будете использовать необработанный указатель ).
  • scoped_ptr подразумевает один (т. Е. Неразделенный), непередаваемый владение.
  • auto_ptr подразумевает одиночное (т. Е. Не разделенное) передаваемое владение. Это умный указатель, который я бы использовал для возврата вновь созданного объекта из функции (функция передает объект вызывающей стороне). auto_ptr страдает тем недостатком, что из-за ограничений языка, когда был определен auto_ptr, его трудно использовать правильно (это дало ему очень плохую репутацию, хотя и предназначалось для умного указателя с единственным переносимым владельцем) семантика была и остается действительной и полезной).
  • unique_ptr имеет ту же семантику, что и auto_ptr, но использует новые функции C ++ 0x (ссылки на значения), чтобы сделать его намного более безопасным (менее подверженным неправильному использованию), чем auto_ptr. Если вы разрабатываете на платформе, где доступен unique_ptr, вы должны использовать его вместо auto_ptr.
  • shared_ptr подразумевает общее владение. На мой взгляд, это чрезмерно используется. Он действительно имеет много допустимых применений, но его следует , а не , просто использовать как параметр по умолчанию.

Я бы также добавил, что shared_ptr часто используется с контейнерами STL, потому что другие классы интеллектуальных указателей не достигают своей предназначенной функции в этом контексте (из-за копирования значений внутри контейнера). Это часто приводит к использованию shared_ptr, когда совместное владение на самом деле не является предполагаемым значением. В этих случаях я предлагаю (где это возможно) использовать классы контейнера-указателя наддува (ptr_vector, ptr_map и т. Д.), Которые обеспечивают (обычно желаемую) семантику контейнера с переносимой, но единственной (не общей) ) владение.

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

[отредактировано, чтобы отметить новый unique_ptr]

2 голосов
/ 29 декабря 2010

Вы, вероятно, должны использовать shared_ptr<>.Трудно быть более конкретным, не зная, что именно вы хотите сделать.Лучше прочитайте его документацию и посмотрите, делает ли он то, что вам нужно.

Разница в производительности, скорее всего, будет незначительной.Только в крайних случаях может произойти заметное влияние, например, копирование этих указателей много миллионов раз в секунду.

1 голос
/ 29 декабря 2010

Зависит.
Лучше использовать общие указатели, чем auto_ptr, которые имеют необычную характеристику смены владельца при назначениях.
Также auto_ptr нельзя использовать в контейнерах.
Также нельзя использовать auto_ptr в качестве возвратазначения, если вы не хотите передавать владение.
Совместно используемые указатели имеют все преимущества интеллектуальных указателей, перегружают соответствующие операторы и действуют как указатели и могут использоваться в контейнерах.Сказав это, они недешевы в использовании.
Вы должны проанализировать свои потребности, чтобы решить, действительно ли вы что-то получаете, избегая накладных расходов на реализацию shared_pointer

1 голос
/ 29 декабря 2010

Я предпочитаю shared_ptr, auto_ptr может вызвать много проблем, и его использование не слишком интуитивно понятно.Если вы ожидаете, что этот объект будет вставлен в контейнер STL, поэтому вы наверняка захотите использовать shared_ptr.

Снизьте производительность, которую у вас есть, но это минимально, и вы можете игнорировать ее большую часть времени.1003 *

0 голосов
/ 29 декабря 2010

Использовать только shared_ptr. С auto_ptr вы можете иметь только одну ссылку на ваш объект. Кроме того, auto_ptr не медленнее, он должен работать быстрее, чем shared_ptr.

Чтобы не задавать такие вопросы, нужно знать, как работают эти умные указатели.

auto_ptr просто хранит указатель на ваш объект и уничтожает его в деструкторе.

Проблема auto_ptr заключается в том, что когда вы пытаетесь скопировать его, он перестает указывать на ваш объект.

Например

auto_ptr a_ptr (новый someClass);

auto_ptr another_ptr = aptr; // после этого another_ptr указывает на ваш класс, но a_ptr больше не указывает на него!

Вот почему я не рекомендую вам использовать auto_ptr.

Общий указатель, подсчитывающий количество умных указателей, указывающих на ваш объект, и уничтожающий ваш объект, когда на него больше нет указателей. Вот почему вы можете иметь более 1 указателя, указывающего на ваш объект.

Но общий указатель тоже не идеален. И если в вашей программе есть циклический граф (когда у вас есть классы A, B и A, есть член shared_ptr, который указывает на B и B, или объекты-члены B имеют shared_ptr, указывающий на A), то A и B никогда не будут удалены, и вы иметь память лизнуть.

Чтобы написать правильный код с shared_ptr, вам нужно быть осторожным, а также использовать слабый_птр. Для получения дополнительной информации смотрите здесь http://www.boost.org/doc/libs/1_45_0/libs/smart_ptr/smart_ptr.htm

...