我了解到 STL 可以禁止程序员将 auto_ptr 放入容器中。例如以下代码将无法编译:
auto_ptr<int> a(new int(10));
vector<auto_ptr<int> > v;
v.push_back(a);
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();
};
}
虽然有一个复制构造函数,但它引用了non-const
。临时对象可能不绑定到这个,因此该类型被有效地禁止在任何使用临时对象的地方的容器内工作;此外,push_back
接受对 的引用const
,因此由于 -const
正确性,新的内部元素不可能通过从push_back
的参数复制构造。
(那个维基百科页面说“由于它的复制语义,auto_ptr 可能不会在可能在其操作中执行元素复制的 STL 容器中使用”;这并不意味着容器会神奇地检查复制构造函数中的代码来决定它是否想让类型作为元素类型工作。相反,它只是关于函数签名。)
无论如何,std::auto_ptr
自 C++11 起已弃用,因为在某些人看来,std::auto_ptr
这很愚蠢。对不起,std::auto_ptr
。
关于编译器如何检测这种情况(或 STL 如何在那里导致错误)的特定问题,您应该阅读编译器的确切输出,它将包含一堆错误,这些错误将导致无法执行转换from const X
toX
因为它丢弃了 const 限定符,其中X
可以是std::auto_ptr<>
直接的,也可以是内部详细信息类型。
特别是,std::vector::push_back
接受参数 by const &
,并且在内部它将尝试使用可用的复制构造函数复制构造动态数组中的元素,在这种情况下std::auto_ptr
需要非常量引用。类似的东西:
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)
}
因为 std::auto_ptr 与 stl 容器不兼容。
std::auto_ptr 使用单一所有权复制语义,stl 容器需要复制构造一个对象(并且一些算法需要分配它)
您应该使用引用计数智能指针 (boost::shared_ptr)
编辑
例如,这是 push_back 的签名
void push_back ( const T& x );
问题是 std::auto_ptr 是特殊的,并且复制构造函数和分配运算符签名不同。它们不是常量。如果您复制它,则修改 auto_ptr。
auto_ptr& operator= (auto_ptr& a) throw();
auto_ptr (auto_ptr& a) throw();
您不能提供满足 push_back 要求的 auto_ptr。
其他答案是关于 auto_ptr 的。
要做你想做的事情,如果 std::unique_ptr 对你可用(C++11),你可以使用 shared_ptr