为什么vector.push_back(auto_ptr)不能编译?

fri*_*ker 6 c++ stl auto-ptr

我了解到STL可以禁止程序员将auto_ptr放入容器中.例如,以下代码无法编译:

    auto_ptr<int> a(new int(10));
    vector<auto_ptr<int> > v;
    v.push_back(a);
Run Code Online (Sandbox Code Playgroud)

auto_ptr有复制构造函数,为什么这段代码甚至可以编译?

Lig*_*ica 11

看看定义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();
    };

}
Run Code Online (Sandbox Code Playgroud)

虽然有一个复制构造函数,但它需要引用const.临时工具可能不会与此绑定,因此在任何使用临时工位的地方都有效禁止该类型的容器内部工作; 另外,push_back接受一个引用const,所以由于const正确性,新的内部元素不可能通过复制构造push_back的参数.

(该维基百科页面说"由于其复制语义,auto_ptr可能不会在可能在其操作中执行元素副本的STL容器中使用";这并不意味着容器会神奇地检查复制构造函数中的代码以决定是否想要使类型作为元素类型工作.相反,它只是函数签名.)

无论如何,std::auto_ptr从C++ 11开始被弃用,因为在一些人看来,这std::auto_ptr是愚蠢的.对不起,std::auto_ptr.

  • @Alessandro:我非常不同意,std :: unique_ptr非常适合解决这些问题.幸运的是,滥用它要困难得多.:) (4认同)

Dav*_*eas 6

关于编译器如何检测这种情况(或者STL如何在那里导致错误)的特定问题,您应该读取编译器的确切输出,它将包含一堆错误,这些错误将导致无法执行转换从const XX它丢弃const限定符,其中X可以是std::auto_ptr<>直接或其他内部细节类型.

特别是,std::vector::push_back接受参数const &,并在内部尝试使用可用的复制构造函数复制构造动态数组内的元素,在std::auto_ptr需要非const引用的情况下.有些东西:

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)
}
Run Code Online (Sandbox Code Playgroud)