Почему неправильно использовать std :: auto_ptr <> со стандартными контейнерами? - PullRequest
204 голосов
/ 21 сентября 2008

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

Ответы [ 6 ]

123 голосов
/ 21 сентября 2008

Стандарт C ++ говорит, что элемент 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 или эквиваленты повышения, если нет C ++ 11. Вот документация библиотеки поддержки для этих умных указателей.

65 голосов
/ 21 сентября 2008

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

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

В частности, при копировании auto_ptr одна из копий освобождается от указателя. Что из этого остается в контейнере, не определено. Следовательно, вы можете случайно потерять доступ к указателям, если храните auto_ptrs в контейнерах.

38 голосов
/ 25 июня 2010

Две супер отличные статьи на эту тему:

17 голосов
/ 21 сентября 2008

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

В Effective STL (Скотт Мейерс), пункт 8, приведено подробное описание того, что может пойти не так, а в Effective C ++ (Скотт Мейерс), пункт 13, не так подробно.

12 голосов
/ 21 сентября 2008

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

4 голосов
/ 30 октября 2012

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

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

Стандарт C ++ 11 (ISO-IEC 14882-2011) в приложении D.10.1, параграф 3:

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

C ++ 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 не определены.
Обоснование : заменено новыми функциями.
Влияние на исходную функцию : допустимый код C ++ 2014, использующий эти шаблоны классов и шаблоны функций, может не скомпилироваться в этом Международный стандарт.

...