Stl 中 auto_ptr只是众多可能的智能指针之一,auto_ptr所做的事情,就是动态分配对象以及当对象不再需要时自动执行清理。
这里是一个简单的代码示例,如果没有auto_ptr,
2 {
3
4 while (data) // 如果还有数据
5 {
6 ALA *pa = readALAData(data); // 取出下一个数据
7 pa->DealProcessAdoption(data); // 处理
8
9 delete pa; // 释放资源
10 }
11 return;
12}
如果在DealProcessAdoption有一个exception,会发生什么事情,因为ProcessAdoption不能捕获他,所以这段代码很危险,所以DealProcessAdoption后面的代码可能会跳过,造成内存泄露。
如果利用try catch去捕获他,会搞得代码很乱,又缺少美观性。
所以Stl提供了一个智能指针来解决这个问题,我们可以先模拟实现一个智能指针的类实现。
2 template < typename Type >
3 class auto_ptr
4 {
5public:
6 auto_ptr(T *p =NULL) :Ptr(p)
7 { }
8 ~auto_ptr()
9 {
10 delete Ptr;
11 }
12private:
13 Type *Ptr;
14} ;
15
16
17 void ProcessAdoption(istream & data)
18 {
19
20 while (data) // 如果还有数据
21 {
22 auto_ptr<ALA> pa(readALADara(data));
23 pa->DealProcessAdoption(data);
24 }
25 return;
26}
这个版本和原先版本的差异只有二处,
第一pa是一智能指针的对象,不是ALA*
第二不用自己去释放delete
然后我看到Effective STL的条款
8:永不建立auto_ptr的容器
关于此可以看的Effective STL的条款8
因为auto_ptr并不是完美无缺的,它的确很方便,但也有缺陷,在使用时要注意避免。首先,不要将auto_ptr对象作为STL容器的元素。C++标准明确禁止这样做,否则可能会碰到不可预见的结果
auto_ptr的另一个缺陷是将数组作为auto_ptr的参数: auto_ptr<char> pstr (new char[12] ); //数组;为定义
然后释放资源的时候不知道到底是利用delete pstr,还是 delete[] pstr;
然后收集了关于auto_ptr的几种注意事项:
1、auto_ptr不能共享所有权。
2、auto_ptr不能指向数组
3、auto_ptr不能作为容器的成员。
4、不能通过赋值操作来初始化auto_ptr
std::auto_ptr<int> p(new int(42)); //OK
std::auto_ptr<int> p = new int(42); //ERROR
这是因为auto_ptr 的构造函数被定义为了explicit
5、不要把auto_ptr放入容器
然后笔者从而推荐的是boost的shared_ptr,然后看完shared_ptr关于智能指针的介绍与例子。
5种针对auto_ptr不足的指针如下:需要详细了解可以去查看相当文档,与测试新代码。
scoped_ptr | <boost/scoped_ptr.hpp> | 简单的单一对象的唯一所有权。不可拷贝。 |
scoped_array | <boost/scoped_array.hpp> | 简单的数组的唯一所有权。不可拷贝。 |
shared_ptr | <boost/shared_ptr.hpp> | 在多个指针间共享的对象所有权。 |
shared_array | <boost/shared_array.hpp> | 在多个指针间共享的数组所有权。 |
weak_ptr | <boost/weak_ptr.hpp> | 一个属于 shared_ptr 的对象的无所有权的观察者。 |
intrusive_ptr | <boost/intrusive_ptr.hpp> | 带有一个侵入式引用计数的对象的共享所有权。 |
1. shared_ptr是Boost库所提供的一个智能指针的实现,shared_ptr就是为了解决auto_ptr在对象所有权上的局限性(auto_ptr是独占的),在使用引用计数的机制上提供了可以共享所有权的智能指针.
2. shared_ptr比auto_ptr更安全
3. shared_ptr是可以拷贝和赋值的,拷贝行为也是等价的,并且可以被比较,这意味这它可被放入标准库的一般容器(vector,list)和关联容器中(map)。
关于shared_ptr的使用其实和auto_ptr差不多,只是实现上有差别,关于shared_ptr的定义就不贴代码了,以为内开源,可以网上找
1、shared_ptr<T> p(new Y);
要了解更多关于auto_ptr的信息,可以查看more effective c++ 的p158页条款28
要了解shared_ptr 类模板信息,可以查看boost 1.37.0中文文档,而且支持数组的shared_array 类模板
出自:http://www.cppblog.com/expter/archive/2009/03/29/78270.html
1 auto_ptr的意义
auto_ptr是一种智能指针,当系统异常退出的时候避免资源泄漏(内存)。
其他的资源还对应其他的智能指针。
2 auto_ptr的使用
std::auto_ptr<int> test(new int(1));
test将是一个auto_ptr的对象,使用一个int指针进行初始化。
test可以象其他指针一样使用,如使用* 使用->但是++不可以使用,以后也许会扩展,其实难对++做越界管理,也许可以放弃一些速度。
当使用auto_ptr的时候,必须使用显式的类型转化来初始化,如auto_ptr<classA> a(new classA)
而不能使用auto_ptr<classA> a = new classA;
3 auto_ptr所有权的转移
auto_ptr对所有权有严格的约定,一个auto_ptr只能控制一个指针,不能控制多个,当auto_ptr拥有一个指针的时候就不能在拥有其他的指针了。同时,不同的auto_ptr不能拥有同一个指针。但是存在这样的情况,不同的auto_ptr可能控制着相同的对象,不要出现这样的情况。
auto_ptr<int> a(new int); 1
auto_ptr<int> b(a); 2
auto_ptr<int> c = b; 3
auto_ptr<int> d(int); 4
d = c; 5
当2发生的时候,a将所有权放弃,b获得所有权。
当3发生时, b将放弃所有权,c获得所有权
当5发生时, c的所有权给d,d将释放自己的所有权,并把对象删除掉。
4 来源和接收
当auto_ptr以参数的形式传递给函数的时候,作用域同样发生了变化,从之前的作用域变成了函数内部的作用域。过程时这样的,当有auto_ptr作为参数传递到函数内部的时候,首先会交接自己的所有权,所有权交给了函数的参数,作用域编程了函数的内部。函数退出时,函数内部的临时变量都会离开作用域,包括传递进来接收到的auto_ptr,auto_ptr会释放自己保存的资源。在函数退出后,申请的资源就消失了,这种情况可能很出乎人的预料,因为c++一般传递参数都是传值,如何都不会改变变量本身的作用域的。
另一个使用方式,在函数内部返回一个指针,可以避免内存泄漏
#include <iostream>
using namespace std;
template<class T>
auto_ptr<T> getAutoPtr()
{
auto_ptr<T> rt(new T);
return rt;
}
int main(void)
{
auto_ptr<int> rt = getAutoPtr<int>();
cout<< "["<< *rt<< "]"<< endl;
return 0;
}
函数的参数可以是auto_ptr<classT>& 类型,当传递auto_ptr的引用的时候,有的时候会传递所有权,有的时候不会,所以永远不要这样做。
当使用const auto_ptr<classT>& 的时候,这个时候如果转移所有权会出错,但是这里存在一个问题,const的意义在于不可以更改传递的参数的数据,但是在这里我们想实现的是不需要传递所有权。这个特性主要应用在模板上,当使用auto_ptr实例话对象的时候也不会出现问题。
所以const auto_ptr<classT>&的意思是不能转移所有权,而不是不能更改数据,这里和c++信息是不一样的,还是少使用好一些。
auto_ptr当作类的成员变量可以避免,当类在构造的时候出现异常,这样如果内存被分配了是不会被释放的,因为如果构造没有完成是不会调用析构函数的,这个时候就没有办法来释放申请的资源了。可以使用
auto_ptr来避免这样的事情发生,如果不想在类种转换所有权,可以使用const来修饰。
5 使用auto_ptr的误区
1 两auto_ptr不要引用同一个对象(t*),这样如果一个auto_ptr释放了资源,另一个或多个就无法获得引用对象的信息。
2 auto_ptr不可以保存array,因为在释放的时候是使用delete,这样就会引起未知的问题。
3 auto_ptr设计成在异常发生的时候,避免内存泄漏,不要乱用。
4 不要在容器中使用auto_ptr,因为无法满足容器的一些要求,比如在copy construct和 “=”操作时,会转移所有权。
出自:http://hi.baidu.com/pangkh2009/blog/item/c2d986de4c91d21a495403f9.html
其他可参考:http://www.cppblog.com/mymsdn/archive/2010/04/07/111882.html