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