Std:: auto_ptr в std:: unique_ptr

С появлением нового стандарта (и частей, уже доступных в некоторых компиляторах), новый тип std::unique_ptr должен заменить std::auto_ptr.

Их использование в точности совпадает (поэтому я могу выполнить глобальный поиск/замену в моем коде (не то, чтобы я это делал, но если бы я это сделал)) или я должен знать о некоторых различиях, которые не очевидны при чтении документации?

Также, если это прямая замена, зачем давать ему новое имя, а не просто улучшать std::auto_ptr?

Ответы

Ответ 1

Вы не можете выполнить глобальный поиск/замену, потому что вы можете скопировать 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.

Ответ 2

std::auto_ptr и std::unique_ptr несовместимы в некоторых случаях и капля замены в других. Таким образом, поиск/замена не является достаточно хорошим. Однако после того, как find/replace, работающий с ошибками компиляции, должен исправить все, кроме странных угловых случаев. Для большинства ошибок компиляции требуется добавить std::move.

  • Переменная области функций:
    100% совместимость, если вы не передаете ее по значению другой функции.
  • Тип возврата:
    не совместимо с 100%, но совместимость с 99% не кажется неправильной.
  • Параметр функции по значению:
    100%, совместимый с одним оговоркой, unique_ptr должен быть передан через вызов std::move. Это просто, поскольку компилятор будет жаловаться, если вы не получите его правильно.
  • Параметр функции по ссылке:
    100% совместимость.
  • Переменная члена класса:
    Это сложно. std::auto_ptr Копировать семантику зло. Если класс запрещает копирование, то 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, тогда вам все равно нужно реорганизовать свой код.

Ответ 3

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 будет иметь совершенно новые возможности: они могут храниться в контейнерах.

Ответ 4

Herb Sutter имеет приятное объяснение GotW # 89:

Что такое сделка с auto_ptr? auto_ptr наиболее ярко характеризуется как доблестная попытка создать unique_ptr перед С++ имела семантику перемещения. auto_ptr теперь устарел и не должен использоваться в новом коде.

Если у вас есть auto_ptr в существующей базе кода, когда вы получаете шанс попробуйте сделать глобальный поиск и замену auto_ptr на unique_ptr; подавляющее большинство применений будет работать одинаково, и оно может ошибка компиляции) или исправить (тихо) ошибку или два, которые вы не знали о вас было.

Другими словами, хотя глобальный поиск и замена могут временно "нарушить" ваш код, вы должны сделать это в любом случае: может потребоваться некоторое время, чтобы исправить ошибки компиляции, но сэкономит вам больше проблем в долгое время.