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
для використання .