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; подавляющее большинство применений будет работать одинаково, и оно может ошибка компиляции) или исправить (тихо) ошибку или два, которые вы не знали о вас было.
Другими словами, хотя глобальный поиск и замена могут временно "нарушить" ваш код, вы должны сделать это в любом случае: может потребоваться некоторое время, чтобы исправить ошибки компиляции, но сэкономит вам больше проблем в долгое время.