在开发过程中,曾经使用过两种C++的智能指针:auto_ptr和shared_ptr,如今,便总结一下,顺便比较比较二者使用中的区别,注意避免入坑的危险。:-D
(一)auto_ptr
它是C++标准库提供的一种智能指针,在构造时获取某个对象的所有权,在析构时,释放该对象。
如下例所示,即为auto_ptr的使用规则:RAII(Resource Acquisition Is Initialization),也称为“资源获取就是初始化”,
是C++语言的一种管理资源、避免泄漏的惯用法。
C++标准保证任何情况下,已构造的对象最终会销毁,即它的析构函数最终会被调用。
简单的说,RAII 的做法是使用一个对象,在其构造时获取资源,
在对象生命期控制对资源的访问使之始终保持有效,
最后在对象析构的时候释放资源。
int *p = new int(10);
std::auto_ptr <int> ap(p);
但是使用auto_ptr,有一些必须注意的问题:
(1)不可以将两个或两个以上的auto_ptr指向同一个对象,因为其中当其中一个auto_ptr的生命期结束时,它就会析构对象,而另一个auto_ptr在析构时,将造成多重析构问题,这是很不安全的内存操作。故而,以下的行为是一定要避免的:
int *p = new int(0);
auto_ptr<int> ap1(p);
auto_ptr<int> ap2(p);
//ap1和ap2都指向一个对象,这就是极危险的,必须防止这么使用
(2)不可使用auto_ptr来管理数组指针。
因为auto_ptr在析构时,使用的是delete,而不是delete[]。所以以下的使用方式是绝对要避免的。
int *pa = new int[10];
auto_ptr<int> ap(pa);
//这种写法是完全错误的,极可能引起内存泄露的危险
(3)auto_ptr强调对“裸”指针的完全占有性。也就是说,一个“裸”指针不能同时被两个以上的“裸”指针所拥有。那么,在拷贝构造函数和赋值中,auto_ptr均采取了“所有权转移”的策略,即原指针将失去对裸指针的所有权。
int *p = new int(10); auto_ptr<int> ap1(p); auto_ptr<int> ap2 = ap1; //这会使得ap1变成了NULL cout << *ap1 <<endl; //错误!此时,对其解引用是不安全的。
如上的错误相对而言,比较容易避免,但是对于以下的代码,错误就较难发现。
void fun(auto_ptr<int> ap) { cout << *ap << endl; } auto_ptr<int> ap(new int(0) ) ; fun(ap); cout << *ap << endl; //错误!对空指针的解引用
上述情况比较隐蔽,这是因为在函数调用时,传参引起了拷贝构造函数的调用,所以原来的指针失去了其所有权。
(4)auto_ptr不具备值语义,所以auto_ptr不能被用在STL容器中。
所谓值语义:使之符合以下条件的类型,设有类 Obj:
那么a == b, a == cObj a; Obj b(a); Obj c; c = a;
显然,auto_ptr并不具有这个特点。
auto_ptr用法要点:
1. 需要包含头文件<memory>。
2. Constructor:explicit auto_ptr(X* p = 0) throw(); 将指针p交给auto_ptr对象托管。
3. Copy constructor:auto_ptr(const auto_ptr&) throw(); template<class Y> auto_ptr(const auto_ptr<Y>& a) throw(); 指针的托管权会发生转移。
4. Destructor: ~auto_ptr(); 释放指针p指向的空间。
5. 提供了两个成员函数 X* get() const throw(); //返回保存的指针
6. 对象中仍保留指针 X* release() const throw(); //返回保存的指针,对象中不保留指针
auto_ptr实现关键点:
1. 利用特点“栈上对象在离开作用范围时会自动析构”。
2. 对于动态分配的内存,其作用范围是程序员手动控制的,这给程序员带来了方便但也不可避免疏忽造成的内存泄漏,毕竟只有编译器是最可靠的。
3. auto_ptr通过在栈上构建一个对象a,对象a中wrap了动态分配内存的指针p,所有对指针p的操作都转为对对象a的操作。而在a的析构函数中会自动释放p的空间,而该析构函数是编译器自动调用的,无需程序员操心。
后面的两点引用于http://blog.csdn.net/monkey_d_meng/article/details/5901392,谢谢作者的耐心讲解!