std :: auto_ptr to std :: unique_ptr


185

З новим стандартом (і деталі, які вже доступні в деяких компіляторах), новий тип std::unique_ptrповинен бути заміною std::auto_ptr.

Чи точно їхнє використання перекривається (тому я можу зробити глобальний пошук / заміну свого коду (не те, що я б це зробив, але якби це зробив)) чи я повинен знати про деякі відмінності, які не видно з читання документації?

Крім того, якщо це пряма заміна, навіщо давати їй нове ім'я, а не просто вдосконалювати std::auto_ptr?

Відповіді:


219

Ви не можете зробити глобальну пошук / заміну, оскільки ви можете скопіювати auto_ptr(з відомими наслідками), але unique_ptrпереміщення можна лише. Все, що схоже

std::auto_ptr<int> p(new int);
std::auto_ptr<int> p2 = p; 

доведеться стати принаймні таким

std::unique_ptr<int> p(new int);
std::unique_ptr<int> p2 = std::move(p);

Що стосується інших відмінностей, unique_ptrможе правильно обробляти масиви (він буде дзвонити delete[], а auto_ptrнамагатиметься викликати delete.


101
з іншого боку, якщо це знайти / замінити, це призведе лише до помилок компіляції, воно не мовчить зламати код, наскільки я бачу. Так це безпечно, якщо ви вручну виправляєте помилки компіляції після цього
jalf

7
@jalf: Дійсно, я не можу придумати зустрічний приклад, який би був чітко визначений auto_ptrs, а UB - унікальними_ptrs.
Cubbi

1
тому, схоже, унікальний_ptr - це вдосконалення auto_ptr: масив підтримки та усунення неоднозначності
Baiyan Huang

92

std::auto_ptrі std::unique_ptrвони несумісні в деяких випадках і падіння заміни в інших. Отже, пошук / заміна недостатньо хороший. Однак після пошуку / заміни роботи через компіляцію помилки повинні виправити все, крім дивних кутових випадків. Більшість помилок компіляції потребує додавання std::move.

  • Змінна область функцій:
    100% сумісна, якщо ви не передаєте її за значенням іншій функції.
  • Тип повернення:
    не 100% сумісний, але 99% сумісний не здається помилковим.
  • Параметр функції за значенням:
    100% сумісний з одним застереженням, unique_ptrs повинен бути переданий під час std::moveвиклику. Цей простий, оскільки компілятор скаржиться, якщо ви не зрозумієте це правильно.
  • Параметр функції за посиланням:
    100% сумісний.
  • Змінна члена класу:
    ця хитра. std::auto_ptrs семантика копії є злом. Якщо клас забороняє копіювати, то std::unique_ptrце падіння заміни. Однак якщо ви намагалися надати класу розумну семантику копіювання, вам потрібно буде змінити std::auto_ptrкод обробки. Це просто, оскільки компілятор скаржиться, якщо ви не зрозумієте це правильно. Якщо ви дозволили копіювати клас з std::auto_ptrчленом без спеціального коду, тоді вам сором і удача.

Якщо підсумовувати, std::unique_ptrце неперервне std::auto_ptr. Він забороняє поведінку під час компіляції, які часто були помилками під час використання std::auto_ptr. Тож якщо ви використовували std::auto_ptrнеобхідний догляд, перехід на його std::unique_ptrповинен бути простим. Якщо ви покладалися на std::auto_ptrдивну поведінку, вам все одно потрібно переробляти код.


8
+1 для "у будь-якому випадку вам потрібно перефактурувати код". auto_ptrs хороший лише за те, що 20.4.5 / 3 каже, що вони хороші.
Cubbi

8
Дозвольте додати до цього, що ви, безумовно, повинні замінити auto_ptr на унікальний_ptr у своєму коді та виправити помилки компіляції. Ви здивуєтеся, скільки помилок буде виявлено.
Bartosz Milewski

36

AFAIK, unique_ptrне є прямою заміною. Основна вада, яку він усуває, - це неявна передача права власності.

std::auto_ptr<int> a(new int(10)), b;
b = a; //implicitly transfers ownership

std::unique_ptr<int> a(new int(10)), b;
b = std::move(a); //ownership must be transferred explicitly

З іншого боку, unique_ptrбудуть мати абсолютно нові можливості: їх можна зберігати в контейнерах.


8
Скотт Майєрс також згадував у своєму пункті "Ефективний C ++" (3-е видання), пункт 13 (стор. 64), що контейнери STL вимагають, щоб їх вміст демонстрував "нормальну" поведінку копіювання, тому контейнери auto_ptrне заборонені.
Цянь Сю

31

Herb Sutter має приємне пояснення щодо GotW # 89 :

Яка угода з auto_ptr? auto_ptr найчастіше характеризується як доблесна спроба створити унікальний_ptr, перш ніж C ++ має семантику переміщення. auto_ptr тепер застарілий і не повинен використовуватися в новому коді.

Якщо у вас є auto_ptr в існуючій кодовій базі, коли ви отримуєте шанс, спробуйте зробити глобальний пошук-заміну авто_ptr на унікальний_ptr; переважна більшість застосувань буде працювати однаково, і це може викрити (як помилку часу компіляції) або виправити (мовчки) помилку чи два, про які ви не знали, що у вас є.

Іншими словами, хоча глобальний пошук і заміна може тимчасово "зламати" ваш код, ви все одно повинні це зробити: це може зайняти деякий час, щоб виправити помилки компіляції, але позбавить вас набагато більше проблем у довгостроковій перспективі.


Чудове посилання. Дуже дякую!
fotNelton
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.