C ++ 03
std::auto_ptr- Можливо, один із оригіналів, яким він страждав від синдрому першої тяги, лише надав обмежені можливості для збору сміття. Першим недоліком є те, що він вимагає deleteруйнування, що робить їх неприйнятними для зберігання виділених масивів ( new[]). Він займає право власності на вказівник, тому два автоматичні вказівники не повинні містити одного об’єкта. Призначення передасть право власності та скине автоматичний покажчик rvalue на нульовий покажчик. Що призводить до, можливо, найгіршого недоліку; їх не можна використовувати в контейнерах STL через вищезазначену неможливість копіювання. Останнім ударом для будь-якого випадку використання є те, що їх планування буде припинено в наступному стандарті C ++.
std::auto_ptr_ref- Це не розумний покажчик, це фактично деталі дизайну, які використовуються разом, std::auto_ptrщоб дозволити копіювання та призначення у певних ситуаціях. Зокрема, його можна використовувати для перетворення non-const std::auto_ptrна значення, використовуючи трюк Colvin -Gibbons, також відомий як конструктор переміщення для передачі права власності.
Навпаки, можливо, std::auto_ptrнасправді не передбачалося використовувати розумний покажчик загального призначення для автоматичного вивезення сміття. Більшість моїх обмежених розумінь та припущень ґрунтуються на ефективному використанні auto_ptr Herb Sutter, і я користуюсь ним регулярно, хоча не завжди найбільш оптимізованим способом.
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, на основі цієї реалізації, це дозволяє не володіти посиланням на a 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для використання .