C ++ 03
std::auto_ptr
- Возможно, один из оригиналов, от которого он страдал от синдрома первого сквозняка, предоставил только ограниченные возможности для сбора мусора. Первым недостатком является то, что он вызывает delete
после уничтожения, что делает их неприемлемыми для хранения объектов, выделенных массивом (new[]
). Указатель становится владельцем указателя, поэтому два указателя авто не должны содержать один и тот же объект. Назначение передаст владение и сбросит автоматический указатель rvalue на нулевой указатель. Что приводит к возможно худшему недостатку; их нельзя использовать в контейнерах STL из-за вышеупомянутой невозможности копирования. Последним ударом по любому варианту использования является то, что в следующем стандарте C ++ они устарели.
std::auto_ptr_ref
- Это не интеллектуальный указатель, это на самом деле деталь проекта, используемая вместе с std::auto_ptr
, чтобы разрешить копирование и назначение в определенных ситуациях. В частности, его можно использовать для преобразования неконстантного std::auto_ptr
в lvalue с использованием трюка Колвина-Гиббона, также известного как конструктор перемещения для передачи права собственности.
Наоборот, возможно, std::auto_ptr
не предназначался для использования в качестве интеллектуального указателя общего назначения для автоматического сбора мусора. Большая часть моего ограниченного понимания и предположений основана на Эффективном использовании Хербом Саттером auto_ptr , и я использую его регулярно, хотя и не всегда самым оптимальным образом.
C ++ 11
std::unique_ptr
- Это наш друг, который заменит std::auto_ptr
, это будет очень похоже, за исключением ключевых улучшений для исправления слабых сторон std::auto_ptr
, таких как работа с массивами, lvalue защита с помощью закрытого конструктора копирования, пригодная для использования с контейнерами и алгоритмами STL и т. д. Поскольку накладные расходы на производительность и объем памяти ограничены, это идеальный кандидат для замены, или, возможно, более удачно описанный как собственный, необработанный указатель. Как следует из «уникального», указатель имеет только одного владельца, как и предыдущий std::auto_ptr
.
std::shared_ptr
- я полагаю, что это основано на TR1 и boost::shared_ptr
, но улучшено, чтобы включить алиасы и арифметику указателей. Короче говоря, он оборачивает умный указатель с подсчетом ссылок вокруг динамически размещаемого объекта. Поскольку «общий» подразумевает, что указатель может принадлежать более чем одному совместно используемому указателю, когда последняя ссылка последнего общего указателя выходит из области видимости, тогда объект будет удален соответствующим образом. Они также являются поточно-ориентированными и могут обрабатывать неполные типы в большинстве случаев. std::make_shared
может использоваться для эффективного построения std::shared_ptr
с одним выделением кучи с использованием распределителя по умолчанию.
std::weak_ptr
- также на основе TR1 и boost::weak_ptr
. Это ссылка на объект, принадлежащий std::shared_ptr
, и поэтому не будет препятствовать удалению объекта, если счетчик ссылок std::shared_ptr
упадет до нуля. Чтобы получить доступ к необработанному указателю, вам сначала нужно получить доступ к std::shared_ptr
, вызвав lock
, который вернет пустой std::shared_ptr
, если срок действия собственного указателя истек и он уже уничтожен. Это в первую очередь полезно, чтобы избежать неопределенного числа ссылок зависания при использовании нескольких интеллектуальных указателей.
подталкивания
boost::shared_ptr
- Вероятно, самый простой в использовании в самых разных сценариях (STL, PIMPL, RAII и т. Д.), Это подсчитанный умный указатель с общей ссылкой. Я слышал несколько жалоб на производительность и накладные расходы в некоторых ситуациях, но, должно быть, я их проигнорировал, потому что не могу вспомнить, что это был за аргумент. По-видимому, он был достаточно популярен, чтобы стать ожидающим стандартным объектом C ++, и на ум не приходит никаких недостатков по сравнению с нормой относительно интеллектуальных указателей.
boost::weak_ptr
- Так же, как и предыдущее описание std::weak_ptr
, основанное на этой реализации, это допускает ссылку на boost::shared_ptr
без владельца. Неудивительно, что вы вызываете lock()
для доступа к «сильному» общему указателю и должны убедиться, что он действителен, так как он мог быть уже уничтожен. Просто убедитесь, что вы не сохранили возвращенный общий указатель и выпустите его из области видимости, как только закончите, иначе вы вернетесь к проблеме циклических ссылок, где ваши счетчики ссылок будут зависать и объекты не будут уничтожены.
boost::scoped_ptr
- Это простой класс интеллектуальных указателей с небольшими накладными расходами, вероятно, предназначенный для более эффективной альтернативы boost::shared_ptr
при использовании. Это сопоставимо с std::auto_ptr
, особенно в том, что его нельзя безопасно использовать в качестве элемента контейнера STL или с несколькими указателями на один и тот же объект.
boost::intrusive_ptr
- Я никогда не использовал это, но, насколько я понимаю, оно предназначено для использования при создании ваших собственных классов, совместимых с интеллектуальным указателем. Вам нужно реализовать подсчет ссылок самостоятельно, вам также нужно будет реализовать несколько методов, если вы хотите, чтобы ваш класс был универсальным, более того, вам нужно было бы реализовать собственную безопасность потоков. С положительной стороны это, вероятно, дает вам самый нестандартный способ выбора и точного выбора того, сколько или как мало «умности» вы хотите. intrusive_ptr
, как правило, более эффективен, чем shared_ptr
, поскольку он позволяет вам выделять одну кучу для каждого объекта. (спасибо Арвид)
boost::shared_array
- это boost::shared_ptr
для массивов. В основном new []
, operator[]
и, конечно, delete []
запекаются. Это может использоваться в контейнерах STL, и, насколько я знаю, все делает boost:shared_ptr
, хотя вы не можете использовать boost::weak_ptr
с ними. Однако вы можете альтернативно использовать boost::shared_ptr<std::vector<>>
для аналогичной функциональности и восстановить способность использовать boost::weak_ptr
для ссылок.
boost::scoped_array
- Это boost::scoped_ptr
для массивов. Как и в случае boost::shared_array
, все необходимые свойства массива запекаются. Этот не подлежит копированию и поэтому не может использоваться в контейнерах STL. Я нашел почти везде, где вы хотели бы использовать это, вы, вероятно, могли бы просто использовать std::vector
. Я никогда не определял, что на самом деле быстрее или имеет меньше накладных расходов, но этот массив с областью видимости кажется гораздо менее сложным, чем вектор STL. Если вы хотите сохранить распределение в стеке, рассмотрите boost::array
.
Qt
QPointer
- Представленный в Qt 4.0, это «слабый» умный указатель, который работает только с QObject
и производными классами, который в среде Qt равен почти всем так что на самом деле это не ограничение. Однако существуют ограничения, а именно то, что он не предоставляет «сильный» указатель, и хотя вы можете проверить, является ли базовый объект допустимым с isNull()
, вы можете обнаружить, что ваш объект уничтожен сразу после того, как вы пройдете эту проверку, особенно в многопоточных средах. , Я считаю, что люди считают это устаревшим.
QSharedDataPointer
- Это «сильный» интеллектуальный указатель, потенциально сравнимый с boost::intrusive_ptr
, хотя он имеет некоторые встроенные средства обеспечения безопасности потоков, но требует включения методов подсчета ссылок (ref
и deref
), что вы можете сделать, создав подкласс QSharedData
. Как и в случае с большей частью Qt, объекты лучше всего использовать посредством достаточного наследования и создания подклассов, все выглядит как задуманное.
QExplicitlySharedDataPointer
- Очень похоже на QSharedDataPointer
, за исключением того, что оно не вызывает неявно detach()
. Я бы назвал эту версию 2.0 QSharedDataPointer
, так как небольшое увеличение контроля в отношении того, когда именно отсоединяться после того, как счетчик ссылок падает до нуля, не особенно ценно для нового объекта.
QSharedPointer
- Атомный подсчет ссылок, потокобезопасный, разделяемый указатель, пользовательские удаления (поддержка массивов), звучит так, как должен быть умный указатель. Это то, что я в основном использую как умный указатель в Qt, и я нахожу его сравнимым с boost:shared_ptr
, хотя, вероятно, значительно больше накладных расходов, как и многие объекты в Qt.
QWeakPointer
- Чувствуете ли вы повторяющийся паттерн?Так же, как std::weak_ptr
и boost::weak_ptr
, он используется вместе с QSharedPointer
, когда вам нужны ссылки между двумя умными указателями, которые в противном случае приводили бы к удалению ваших объектов.
QScopedPointer
- Это имя также должно выглядеть знакомо и на самом деле основано на boost::scoped_ptr
в отличие от версий общего доступа и слабых указателей Qt.Он функционирует для предоставления интеллектуального указателя одного владельца без дополнительных затрат QSharedPointer
, что делает его более подходящим для совместимости, безопасного кода исключений и всех вещей, которые вы можете использовать std::auto_ptr
или boost::scoped_ptr
для.