Why is it wrong to use std::auto_ptr<> with standard containers?
Asked Answered
M

6

227

Why is it wrong to use std::auto_ptr<> with standard containers?

Metaphysics answered 21/9, 2008 at 17:27 Comment(5)
Definitely a +1 on this because I've seen so many people get this wrong. It's a great question to ask.Tenebrae
Please read also the related item. This question is considered here from the other side. May be helpful to understand more about auto_ptr and STL containers. #8631052Retinitis
C++ FAQ: Can I have a container of smart pointers to my objects?Incorruption
move semantic and unique_ptr were designed to avoid the problems related to auto_ptr. In C++ 03, the language was not powerful enough to write a class like auto_ptr that behave correctly and safely in all scenarios as the compiler and the language were not able to distinguish l and r values so some "hacks" were used to get the desired behavior most of the time.Therapist
Nice article: STL Containers and Auto_ptrs - Why They Don't Mix quantstart.com/articles/…Lithometeor
P
126

The C++ Standard says that an STL element must be "copy-constructible" and "assignable." In other words, an element must be able to be assigned or copied and the two elements are logically independent. std::auto_ptr does not fulfill this requirement.

Take for example this code:

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.

To overcome this limitation, you should use the std::unique_ptr, std::shared_ptr or std::weak_ptr smart pointers or the boost equivalents if you don't have C++11. Here is the boost library documentation for these smart pointers.

Pointillism answered 21/9, 2008 at 17:27 Comment(5)
You should also consider the boost pointer containers, if you don't need shared ownership.Discourse
unique_ptr also disallows copying, so certain STL operations will not work correctly unless they can use its move semantics.Demoniac
"To overcome this limitation, you should use the std::unique_ptr": that class template can only exist because of move semantics (its specification requires rvalue references), so it fundamentally requires C++11. However (and related) the C++11 Standard no longer says that an STL element type must be "copy-constructible" and "assignable"; being move-constructible and move-assignable suffices. Indeed unique_ptr instances are only move-constructible and move-assignable. But so are auto_ptr instances! As a consequence, in C++11 you may do with auto_ptr what you can do with unique_ptr.Tweedy
@MarcvanLeeuwen unless you reset and release as neededEphemerality
@ratchetfreak: Hmm, I don't understand. What? "unless you reset and release", I don't see how that applies to anything in my comment. Note that both auto_ptr and unique_ptr have both these methods, and they do the same thing in both cases.Tweedy
K
67

The copy semantics of auto_ptr are not compatible with the containers.

Specifically, copying one auto_ptr to another does not create two equal objects since one has lost its ownership of the pointer.

More specifically, copying an auto_ptr causes one of the copies to let go of the pointer. Which of these remains in the container is not defined. Therefore, you can randomly lose access to pointers if you store auto_ptrs in the containers.

Knickknack answered 21/9, 2008 at 17:29 Comment(0)
E
39

Two super excellent articles on the subject:

Ecclesia answered 25/6, 2010 at 19:1 Comment(5)
Because I think that in the intervening nearly two years, he probably dealt with the problem at hand.Than
@DeadMG: yes, you are correct. But that was not my purpose. If someone comes to this thread sometime and wants to learn about auto_ptr and stuff, these links will be helpful, I am sure.Ecclesia
There's plenty of duplicates that are more recent.Than
@DeadMG: This question wasn't closed as duplicate and is therefore open for extension. Lazer said what was not said before here. I guess he came by by chance.Gobetween
The explanations in the second link, which analyze the problem after calling sort(), are clearer than all the answers here.Cindicindie
C
17

The STL containers need to be able to copy the items you store in them, and are designed to expect the original and the copy to be equivalent. auto pointer objects have a completely different contract, whereby copying creates a transfer of ownership. This means that containers of auto_ptr will exhibit strange behaviour, depending on usage.

There is a detailed description of what can go wrong in Effective STL (Scott Meyers) item 8 and also a not-so-detailed description in Effective C++ (Scott Meyers) item 13.

Croatian answered 21/9, 2008 at 17:40 Comment(0)
F
12

STL containers store copies of contained items. When an auto_ptr is copied, it sets the old ptr to null. Many container methods are broken by this behavior.

Falchion answered 21/9, 2008 at 17:44 Comment(2)
But, when using unique_ptr you get pretty much the same thing since only one unique_ptr can have the ownership of the object?Janssen
@Janssen unique_ptr like any proper C++11 object can only transfer ownership of its resource when move-constructed or -assigned, ensuring that the programmer must deliberately pass an std::move(sourceObject) or a temporary, rather than passing an lvalue and unintuitively/unpredictably having it mutated by the copy-assignment... which, as emphasised thoroughly here, was a core problem of auto_ptr.Burton
M
4

C++03 Standard (ISO-IEC 14882-2003) says in clause 20.4.5 paragraph 3:

[...] [Note: [...] auto_ptr does not meet the CopyConstructible and Assignable requirements for Standard Library container elements and thus instantiating a Standard Library container with an auto_ptr results in undefined behavior. — end note]

C++11 Standard (ISO-IEC 14882-2011) says in appendix D.10.1 paragraph 3:

[...] Note: [...] Instances of auto_ptr meet the requirements of MoveConstructible and MoveAssignable, but do not meet the requirements of CopyConstructible and CopyAssignable. — end note ]

C++14 Standard (ISO-IEC 14882-2014) says in appendix C.4.2 Annex D: compatibility features:

Change: The class templates auto_ptr, unary_function, and binary_function, the function templates random_shuffle, and the function templates (and their return types) ptr_fun, mem_fun, mem_fun_ref, bind1st, and bind2nd are not defined.
Rationale: Superseded by new features.
Effect on original feature: Valid C ++ 2014 code that uses these class templates and function templates may fail to compile in this International Standard.

Merill answered 30/10, 2012 at 14:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.