Почему неправильно использовать std:: auto_ptr <> со стандартными контейнерами?

Почему неправильно использовать std::auto_ptr<> со стандартными контейнерами?

Ответ 1

В стандарте С++ говорится, что элемент STL должен быть "копируемым" и "назначаемым". Другими словами, элемент должен быть назначен или скопирован, а два элемента логически независимы. std::auto_ptr не выполняет это требование.

Возьмем, к примеру, этот код:

class X
{
};

std::vector<std::auto_ptr<X> > vecX;
vecX.push_back(new X);

std::auto_ptr<X> pX = vecX[0];  // vecX[0] is assigned NULL.

Чтобы преодолеть это ограничение, вы должны использовать std::unique_ptr, std::shared_ptr или std::weak_ptr умные указатели или эквиваленты повышения, если у вас нет С++ 11. Ниже приведена документация по ускорению для этих интеллектуальных указателей.

Ответ 2

Символы копии auto_ptr несовместимы с контейнерами.

В частности, копирование одного auto_ptr в другое не создает двух равных объектов, поскольку он потерял право собственности на указатель.

Более конкретно, копирование auto_ptr приводит к тому, что одна из копий отпускает указатель. Какой из них остается в контейнере, не определен. Таким образом, вы можете случайно потерять доступ к указателям, если вы храните auto_ptrs в контейнерах.

Ответ 4

Контейнеры STL должны иметь возможность копировать элементы, которые вы храните в них, и должны рассчитывать, что оригинал и копия будут эквивалентными. объекты автоматического указателя имеют совершенно другой контракт, при котором копирование создает передачу права собственности. Это означает, что контейнеры auto_ptr будут демонстрировать странное поведение, в зависимости от использования.

Существует подробное описание того, что может пойти не так в статье 8 "Эффективный STL (Скотт Майерс)", а также не столь подробное описание в статье "Эффективный С++" (Скотт Майерс).

Ответ 5

Контейнеры STL хранят копии содержащихся элементов. Когда auto_ptr копируется, он устанавливает старый ptr равным null. По этой причине многие методы контейнера нарушены.

Ответ 6

Стандарт С++ 03 (ИСО-МЭК 14882-2003) гласит в пункте 20.4.5, пункт 3:

[...] [ Примечание: [...] auto_ptr не отвечает требованиям CopyConstructible и Assignable для стандартной библиотеки элементов контейнера и, таким образом, создание контейнера стандартной библиотеки с auto_ptr приводит к поведению undefined. - end note]

Стандарт С++ 11 (ISO-IEC 14882-2011) гласит в добавлении D.10.1 пункт 3:

[...] Примечание: [...] Экземпляры auto_ptr отвечают требованиям MoveConstructible и MoveAssignable, но не соответствуют требованиям CopyConstructible и CopyAssignable. - end note]

Стандарт С++ 14 (ISO-IEC 14882-2014), говорится в добавлении C.4.2  Приложение D: возможности совместимости:

Изменить: шаблоны классов auto_ptr, unary_function и binary_function, шаблоны функций random_shuffle и функциональные шаблоны (и их типы возврата) ptr_fun, mem_fun, mem_fun_ref, bind1st и bind2nd не определены.
Обоснование: Заменены новыми функциями.
Влияние на оригинальную функцию: действительный код С++ 2014, который использует эти шаблоны классов и шаблоны функций, может не скомпилироваться в этом Международный стандарт.

Ответ 7

Вы не можете поместить объект auto_ptr в std::vector в любом случае из-за const-correctness. Вы должны получить ошибку компиляции.