Ответ 1
С++ 03
std::auto_ptr
- Возможно, один из оригиналов, которые он перенес с синдромом первого проекта, предоставил только ограниченные средства сбора мусора. Первый недостаток заключается в том, что он вызывает delete
при уничтожении, что делает их неприемлемыми для размещения выделенных объектов (new[]
). Он берет на себя ответственность за указатель, поэтому два указателя не должны содержать один и тот же объект. Присвоение переносит право собственности и reset указатель auto-значения rval на нулевой указатель. Это приводит к худшему недостатку; они не могут использоваться в контейнерах STL из-за вышеупомянутой невозможности копирования. Последним ударом для любого варианта использования является то, что они будут устаревать в следующем стандарте С++.
std::auto_ptr_ref
- это не умный указатель, который на самом деле представляет собой конструктивную деталь, используемую совместно с std::auto_ptr
, чтобы разрешить копирование и назначение в определенных ситуациях. В частности, его можно использовать для преобразования неконстантного std::auto_ptr
в lvalue с использованием трюка Colvin-Gibbons, также известного как move constructor для переноса собственность.
Напротив, возможно, std::auto_ptr
не предназначался для использования в качестве универсального интеллектуального указателя для автоматической сборки мусора. Большая часть моего ограниченного понимания и предположений основана на "Эффективное использование auto_ptr" Herb Sutter, и я использую его регулярно, хотя не всегда самым оптимизированным образом.
С++ 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 и т.д.), это общая ссылка считал умный указатель. В некоторых ситуациях я слышал несколько жалоб на производительность и накладные расходы, но я, должно быть, проигнорировал их, потому что не могу вспомнить, что такое аргумент. По-видимому, он был достаточно популярен, чтобы стать ожидающим стандартным объектом С++, и нет никаких недостатков в отношении нормы относительно умных указателей.
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()
, вы можете обнаружить, что ваш объект будет уничтожен сразу после прохождения этой проверки, особенно в многопоточных средах, Я считаю, что люди Qt считают это устаревшим.
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
для.