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

混江龙づ霸主 提交于 2019-12-22 05:43:15

问题


I learned that STL can forbid programmer putting an auto_ptr into a container. For example following code wouldn't compile:

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

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


回答1:


Looking at 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 takes a reference to non-const. Temporaries may not bind to this, so the type is effectively prohibited from working inside containers in any place where temporaries are used; in addition, push_back accepts a reference to const, so due to const-correctness it's impossible for the new, internal element to by copy-constructed from push_back's argument.

(That Wikipedia page says that "because of its copy semantics, auto_ptr may not be used in STL containers that may perform element copies in their operations"; this doesn't mean that containers magically examine the code inside the copy constructor to decide whether it wants to make the type work as an element type. Instead, it's just about the function signature.)

Anyway, std::auto_ptr is deprecated as of C++11 because, in the opinion of some, std::auto_ptr is silly. Sorry, std::auto_ptr.




回答2:


On the particular issue of how does the compiler detect that situation (or how does the STL cause an error there), you should read the exact output of the compiler, it will contain a bunch of errors that will lead to failure to perform a conversion from const X to X as it discards the const qualifier, where X can either be std::auto_ptr<> directly or else an internal detail type.

In particular, std::vector::push_back takes the argument by const &, and internally it will try to copy construct an element inside the dynamic array using the available copy constructor, which in the case of std::auto_ptr requires a non-const reference. Something in the lines of:

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)
}



回答3:


The other answers are bang on about auto_ptr.

To do what you are trying to do use std::unique_ptr if its available to you (C++11) if not you can use a shared_ptr




回答4:


Because std::auto_ptr is not compatible with stl container.

std::auto_ptr is using single ownership copy semantic, the stl container needs to copy construct an object (and some algorithms need to assign it)

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

EDIT

For example, this is the signature of push_back

void push_back ( const T& x );

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

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

auto_ptr (auto_ptr& a) throw();

You cannot provide an auto_ptr that fulfil the requirement of push_back.



来源:https://stackoverflow.com/questions/7359276/why-vector-push-backauto-ptr-wouldnt-compile

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!