Умные указатели в контейнере, такие как std :: vector? - PullRequest
19 голосов
/ 02 января 2011

Я узнаю об интеллектуальных указателях (std::auto_ptr) и просто прочитал здесь и здесь , что интеллектуальные указатели (std::auto_ptr) не следует помещать в контейнеры (т. Е. std::vector) потому что даже большинство компиляторов не будут жаловаться, и это может показаться правильным. Не существует правила, которое гласит, что интеллектуальные указатели не будут внутренне скопированы (например, классом vector) и не передадут свое владение, тогда указатель станет NULL. В конце концов все облажается.

На самом деле, как часто это происходит?

Иногда у меня есть векторы указателей, и если в будущем я решу, что хочу иметь вектор умных указателей, какие бы у меня были варианты?

Мне известны библиотеки C ++ 0x и Boost, но сейчас я бы предпочел придерживаться подхода STL.

Ответы [ 5 ]

16 голосов
/ 02 января 2011

Да, вы действительно не можете использовать std::auto_ptr со стандартными контейнерами. std::auto_ptr копии не являются эквивалентными, и потому что стандартные контейнеры (и алгоритмы) могут копировать свои элементы по желанию, это все портит. Таким образом, операция копирования std::auto_ptr имеет значение , отличное , чем простая копия объекта: это означает передача права собственности .

Ваши варианты:

  1. Используйте библиотеку Boost Smart Pointers . Возможно, это ваш лучший вариант.
  2. Используйте примитивные указатели. Это быстро и безопасно, если вы правильно управляете указателями. Иногда это может быть сложным или трудным. Например, вам придется самостоятельно решать (избегать) проблемы двойного удаления.
  3. Используйте свой собственный умный указатель подсчета ссылок. Это было бы глупо; используйте Boost Smart Pointer.
9 голосов
/ 02 января 2011

Проблема, на которую вы ссылаетесь, касается auto_ptr, поскольку она переносит владельца на копию. shared_ptr и unique_ptr прекрасно работают с контейнерами.

3 голосов
/ 02 января 2011

Любой тип, который вы используете со стандартным шаблоном контейнера, должен соответствовать требованиям для этого контейнера.В частности, тип должен удовлетворять требованиям для CopyConstructible и Назначаемых типов .

Многие интеллектуальные указатели удовлетворяют этим требованиям и могут использоваться со стандартными контейнерами, но std::auto_ptr не является одним из них, поскольку копии std::auto_ptr не эквивалентны источнику, из которого они были созданы или назначены.

Хотя некоторые реализации стандартного контейнера могут работать с auto_ptr, в некоторых ситуациях это опаснополагаться на такие детали реализации.

2 голосов
/ 02 января 2011

теоретически вы можете использовать std::auto_ptr с контейнерами STL, если вы полностью понимаете их внутреннюю реализацию и не делаете ничего, что может потерять владение auto_ptr, но практически намного безопаснее использовать контейнеры с необработанными ptrs.

"На самом деле, как часто это происходит?" - это очень опасный вопрос сам по себе. Во-первых, STL - это не единая стандартная реализация, их много. Каждый из них может реализовывать контейнеры по-разному, поэтому ваш тщательно настроенный код, позволяющий избежать всех мин «auto_ptr в контейнерах», может осуществить пакетное переключение на другую реализацию STL. Кроме того, обслуживание вашего кода будет очень сложным, любое корректно выглядящее изменение в вашем коде может сломать вашу программу. как вы можете запомнить это или заставить других сопровождающих вспомнить? Размещать предупреждения в любом месте, где могут произойти такие изменения? невозможно.

Итак, вывод: это просто плохая идея, которая не приносит ничего, кроме головной боли

1 голос
/ 30 августа 2014

Для классов, которые имеют элемент данных auto ptr, у меня всегда есть метод clone, который возвращает новый auto ptr.Затем я реализую метод присваивания и конструктор копирования, который вызывает метод клона (и никогда не используется по умолчанию как оператор присваивания auto ptr).Таким образом, вы можете безопасно использовать класс в контейнерах STL.

...