Почему unique_ptr можно использовать с контейнерами std, например с векторами <>?
Я понимаю, что auto_ptr нельзя использовать с векторами, поскольку auto_ptr не соответствует требованию быть копируемым конструктором. Поскольку копируемый auto_ptr изменяется, копирование не приводит к двум точным копиям, нарушая тем самым конструкцию копии.
Unique_ptr также, кажется, делает то же самое; он изменяет копируемый объект - для элемента указателя копируемого объекта устанавливается значение nullptr. Тогда как можно использовать uinque_ptr с векторами, а не с auto_ptrs?
Правильно ли мое понимание или я что-то здесь упускаю?
auto_ptr <int> autoPtr(new int);
vector < auto_ptr <int> > autoVec;
autoVec.push_back(autoPtr); //compiler error..why?
unique_ptr <int> uniquePtr(new int);
vector < unique_ptr <int> > uniqueVec;
uniqueVec.push_back(std::move(uniquePtr)); //okay..why?
2 ответа
Проблема с auto_ptr
было то, что операция, которая не должна была изменить объект, изменила его. Конструктор копирования изменил источник.
unique_ptr
не имеет конструктора копирования. У него есть конструктор перемещения. Конструктор перемещения также изменяет исходный код, но это ожидаемо, и универсальный код может различать ситуации, в которых используется конструктор копирования, и ситуации, в которых используется конструктор перемещения.
vector
(и другие контейнеры) не просто волшебным образом работали с unique_ptr
однажды это было написано. Их нужно было обновить, чтобы они могли работать только с типами перемещения. Это было сделано в C++11. Эту модификацию можно было сделать, потому что перемещение и копирование - это разные операции. Не было возможности сделать то же самое для auto_ptr
потому что у этого класса был странный конструктор копирования.
Ошибка компиляции из-за попытки изменить auto_ptr const&
формальный аргумент (копируя его) в push_back
реализация.
Вместо
autoVec.push_back(autoPtr);
ты можешь сделать
autoVec.emplace_back( autoPtr.release() );
или более напрямую (не используя autoPtr
переменная)
autoVec.emplace_back( new int(42) );
Однако, хотя это работает в техническом смысле (отказ от ответственности: код даже не просматривается никаким компилятором), у вас все еще есть проблема auto_ptr
элементы обнулялись в результате попытки копирования. Так что это все очень и очень небезопасно. Дополнительно, auto_ptr
устарел в C++11; Я не знаю, был ли он вообще удален сейчас, но это не исключено.