Why won't vector.push_back (auto_ptr) compile?

I found out that STL can prevent a programmer from putting auto_ptr in a container. For example, the following code will not compile:

auto_ptr<int> a(new int(10)); vector<auto_ptr<int> > v; v.push_back(a); 

auto_ptr has a copy constructor, why can this code even compile?

+6
source share
4 answers

Considering the definition of std::auto_ptr :

 namespace std { template <class Y> struct auto_ptr_ref {}; template <class X> class auto_ptr { public: typedef X element_type; // 20.4.5.1 construct/copy/destroy: explicit auto_ptr(X* p =0) throw(); auto_ptr(auto_ptr&) throw(); template <class Y> auto_ptr(auto_ptr<Y>&) throw(); auto_ptr& operator=(auto_ptr&) throw(); template <class Y> auto_ptr& operator=(auto_ptr<Y>&) throw(); auto_ptr& operator=(auto_ptr_ref<X>) throw(); ~auto_ptr() throw(); // 20.4.5.2 members: X& operator*() const throw(); X* operator->() const throw(); X* get() const throw(); X* release() throw(); void reset(X* p =0) throw(); // 20.4.5.3 conversions: auto_ptr(auto_ptr_ref<X>) throw(); template <class Y> operator auto_ptr_ref<Y>() throw(); template <class Y> operator auto_ptr<Y>() throw(); }; } 

Although there is a copy constructor, it refers to non const . Temporary persons cannot contact this, therefore the type is actually forbidden to work inside containers anywhere where temporary resources are used; in addition, push_back accepts a reference to const , therefore, due to const correction, this is not possible for a new internal element by copying from the push_back argument.

(This Wikipedia page says that “because of its copy semantics, auto_ptr cannot be used in STL containers that can execute copies of elements in their operations”, this does not mean that containers magically scan the code inside the copy constructor to decide if it wants to make the type work as the type of the element, not just the signature of the function.)

In any case, std::auto_ptr deprecated from C ++ 11 because, according to some, std::auto_ptr stupid. Sorry, std::auto_ptr .

+11
source

Due to the specific problem of how the compiler detects this situation (or how an STL error occurs there), you should read the exact output of the compiler, it will contain a bunch of errors that will lead to a failure, perform the conversion from const X to X , since it discards the specifier const, where X can be either std::auto_ptr<> or the internal type of the part.

In particular, std::vector::push_back accepts the argument const & , and internally it will try to copy the element structure inside the dynamic array using the available copy constructor, which in the case of std::auto_ptr requires non-constant Help. Something in the lines:

 void push_back( std::auto_ptr<int> const & x ) { // ensure enough capacity if needed... new (buffer + size()) std::auto_ptr<int>( x ); // !!! cannot bind x to non-const& // complete the operation (adjust end pointer, and such) } 
+6
source

Since std :: auto_ptr is not compatible with the stl container.

std :: auto_ptr uses the semantics of a single-user copy, the stl container must copy the construction of the object (and some algorithms must assign it)

You should use a smart pointer with reference counting (boost :: shared_ptr)

EDIT

For example, this is the signature push_back

 void push_back ( const T& x ); 

The problem is that std :: auto_ptr is special, and the copy constructor and assign the operator signature are different. They are NOT const. You change auto_ptr if you copy it.

 auto_ptr& operator= (auto_ptr& a) throw(); auto_ptr (auto_ptr& a) throw(); 

You cannot provide auto_ptr that satisfy the push_back requirement.

0
source

Other answers to the question about auto_ptr.

To do what you are trying to do, use std :: unique_ptr if it is available to you (C ++ 11) if you cannot use shared_ptr

0
source

Source: https://habr.com/ru/post/896955/


All Articles