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для чего.