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
. Это ссылка на объект, принадлежащий a, 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
с ними. Однако в качестве альтернативы вы можете использовать a 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
для чего.