Почему unique_ptr работает, но auto_ptr не работает с STL - PullRequest
0 голосов
/ 09 ноября 2019

Я ссылался на множество ссылок на StackOverflow по этим вопросам, где причина auto_ptr неэффективной работы с STL в том, что std::auto_ptr<> не удовлетворяет требованиям быть копируемыми и назначаемыми (так как auto_ptr имеет подделкуконструктор копирования, который в основном передает владение).

Но даже unique_ptr не имеет копирующего ctor и оператора присваивания (он отключен), так как же выполняется требование конструирования и назначения для копирования?

Ответы [ 3 ]

5 голосов
/ 09 ноября 2019

Вы смотрите на все это в обратном направлении.

В C ++ 98/03 мы получили auto_ptr. Этот тип лжет всем, притворяясь, что он поддерживает семантику копирования, когда на самом деле копирование делает что-то очень похожее на операцию копирования. Следовательно, любой тип, основанный на типе, обеспечивающем семантику копирования, например некоторые контейнеры, не сможет получить auto_ptr. Конечно, вы узнаете, только когда ваш код станет нефункциональным, а не во время компиляции.

В C ++ 11 мы получили unique_ptr, тип, который явно не обеспечивает семантику копирования. Вместо этого он предоставляет семантику перемещения и предоставляет их правильно. Следовательно, любой тип, основанный на типе, обеспечивающем семантику копирования, не сможет скомпилироваться, если ему дано unique_ptr.

Однако , причина unique_ptr возникла вообще, потому что концепцияперемещения объекта был добавлен в язык в C ++ 11. Когда в язык добавляются новые концепции, существующие инструменты, такие как требования стандартной библиотеки, часто переоцениваются относительно этой языковой функции.

Например, типы, для которых ранее требовалась семантика копирования, не обязательно должны были сохранять это. требование. Контейнеры C ++ 98/03, которым требовалась семантика копирования, были обновлены в C ++ 11, чтобы требовать (не исключая) только семантику перемещения из типа.

Так что unique_ptr не удовлетворяет некоторому требованию, что auto_ptrне. Дело в том, что язык изменился и больше не нуждается в этом требовании, но auto_ptr все еще лгал о том, что он сделал, поэтому для обратной совместимости мы создали новый тип, который уважал новые возможности языка и не лгал людям.

1 голос
/ 09 ноября 2019

auto_ptr выглядит как копия конструируемая / назначаемая, потому что она имеет конструктор копирования и оператор присваивания.

Проблема состоит в том, что его конструктор и назначение копирования не реализуют семантику копирования, а вместо этого перемещают семантику. Это удивляет интерфейс auto_ptr и делает его непригодным для использования в контейнерах, которые присваивают элементы внутренне (например, vector).

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

Но даже unique_ptr не имеет копирующего ctor и оператора присваивания (его отключено)

unique_ptr не должен быть копируемым или назначаемым. Для большинства случаев достаточно быть перемещаемым, конструируемым и назначаемым.

unique_ptr может заменить любое использование auto_ptr и не имеет проблем с auto_ptr. Начиная с C ++ 11, где был представлен unique_ptr, а также языковая поддержка перемещения, auto_ptr устарел, а с C ++ 17 auto_ptr был удален из стандартной библиотеки.

1 голос
/ 09 ноября 2019

Я предполагаю, что вы имеете в виду использование умных указателей с контейнерами STL.

auto_ptr может, но не должен использоваться , поскольку его конструктор копирования может случайно перемещать данные (он был разработан до того, как семантика перемещения со ссылками на rvalue была добавлена ​​в C ++ 11).

unique_ptr не имеет конструктора копирования, поэтому его нельзя использовать в контейнерах STL. Операции, которые копируют указатель, не будут работать, но это то, что делает его безопасным. Вы все еще можете явно использовать переместить итераторы или emplace, чтобы получить не копируемые элементы в контейнеры.

Примеры использования unique_ptr в контейнерах здесь: Так что unique_ptr можно безопасно использовать в коллекциях stl

...