标签:
为什么auto_ptr不可以作为STL标准容器的元素
假如有这样的一段代码,是否能够运行?
1
2
3
4
5
6
7
8
9
|
int
costa_foo() { vector<
auto_ptr< int >
> v(10); int
i=0; for (;i<10;i++) {
v[i]=auto_ptr< int >( new
int (i)); }
} |
错误出在这一行:
1
|
vector<
auto_ptr< int >
> v(10); |
auto_ptr的拷贝构造函数是这样写的:
1
|
auto_ptr(auto_ptr&
__a) throw ()
: _M_ptr(__a.release()) { } |
可以看出来, 在拷贝构造一个auto_tr的时候, 必需要把参数的那个auto_ptr给release掉,然后在把参数的_M_ptr指针赋值给自己的_M_ptr指针。补充说明一下, _M_ptr是auto_ptr的一个成员,指向auto_ptr管理的那块内存,也就是在auto_ptr生命周期之外被释放掉的那块内存。
当看到这里的时候,整个问题已经能解释通了。STL容器在分配内存的时候,必须要能够拷贝构造容器的元素。而且拷贝构造的时候,不能修改原来元素的值。而auto_ptr在拷贝构造的时候,一定会修改元素的值。所以STL元素不能使用auto_ptr。
不过,还有一个很重要的问题没有解释。那就是为什么在设计auto_ptr的时候,拷贝构造要修改参数的值呢?
其实这问题很简单,不看代码也可以解释清楚。auto_ptr内部有一个指针成员_M_ptr,指向它所管理的那块内存。而拷贝构造的时候,首先把参数的_M_ptr的值赋值给自己的_M_ptr,然后把参数的_M_ptr指针设成NULL,。如果不这样设计,而是直接把参数的_M_ptr指针赋值给自己的, 那么两个auto_ptr的_M_ptr指向同一块内存,在析构auto_ptr的时候就会出问题: 假如两个auto_ptr的_M_ptr指针指向了同一块内存,那么第一个析构的那个auto_ptr指针就把_M_ptr指向的内存释放掉了,造成后一个auto_ptr在析构时释要放一块已经被释放掉的内存,这明显不科学,会产生程序的段错误而crash掉。
而shared_ptr则不存在这个问题, 在拷贝构造和赋值操作的时候,只会引起公用的引用计数的+1,不存在拷贝构造和赋值操作的参数不能是const的问题。
总结:
1 auto_ptr不能作为STL标准容器的元素。
2 auto_ptr在拷贝复制和赋值操作时,都会改变参数。这是因为两个auto_ptr不能管理同一块内存。
标签:
原文地址:http://blog.csdn.net/u014082714/article/details/44260975