C++ 智能指针auto_ptr详解

1. auto_ptr 的设计动机:

 函数操作经常依照下列模式进行:

  • 获取一些资源
  • 执行一些动作
  • 释放所获取的资源

那么面对这些资源的释放问题就会出现下面的两种情况:

  • 一开始获得的资源被绑定于局部对象,那么当函数退出的时候,这些局部对象的析构函数被自动的调用,从而自动释放掉这些资源;
  • 一开始获得的资源是通过某种显示手段获取,而且并没有绑定在任何对象身上,那么必须以显式的方式释放。这种情况常常发生在指针身上;

例子:

1 void f()
2 {
3       ClassA* ptr = new ClassA();
4       ...
5       delete ptr;
6 }    

上述代码的真正的问题在于: 一旦在...中的某处发生异常,那么f()函数将立即退出,根本不会去调用函数尾端的delete语句。结果可能会造成内存的遗失,或者称为资源的遗失。

 

上述问题的一个解决方案是:

 1 void f()
 2 {
 3      ClassA*  ptr = new ClassA();
 4 
 5      try
 6     {
 7         ...  
 8     }
 9     catch(...)
10     {
11         delete ptr;
12         throw; 
13      }
14      
15      delete ptr;    
16 }

为了在异常发生时处理对象的删除工作,程序代码就会变得非常复杂和累赘!

为此,引入了智能指针的概念:

智能指针应该保证:无论在何种情形下,只要自己被销毁,就一定要连带释放其所指向的资源。由于智能指针本身就是区域变量,所以无论是正常推出,还是异常推出,它都一定被销毁,auto_ptr正是这种指针。

auto_ptr是这样的一种指针: 它是"其所指向的对象"的拥有者。所以,当身为对象拥有者的auto_ptr被销毁时,该对象也将被销毁。auto_ptr要求一个对象只能有一个拥有者,严禁一物二主。(天地之间物各有主,苟非吾之所有,虽一毫而莫取)。

下面我们通过一个实例来认识auto_ptr的使用:

 1 #include <iostream>
 2 #include <string>
 3 #include <memory>
 4 
 5 using namespace std;
 6 
 7 class Test
 8 {
 9     public:
10         Test(const string& psg);
11         string getMsg();
12     private:
13         string msg;
14 };
15 
16 Test::Test(const string& psg)
17 {
18     msg = psg;
19 }
20 
21 string Test::getMsg()
22 {
23     return msg;
24 }
25 
26 int main(void)
27 {
28     std::auto_ptr<Test> ptr(new Test("This is the end of the world!"));
29     cout<<ptr->getMsg()<<endl;
30     return 0;
31 }

初始化一个auto_ptr时,将一个指针作为参数传递给auto_ptr的构造函数。而不能使用赋值操作符。

 

2. auto_ptr拥有权的转移:
auto_ptr所界定的是一种严格的拥有权观念。也就是说,由于一个auto_ptr会删除其所指向的对象,所以这个对象绝对不能被其他对象同时"拥有"。绝对不可以出现多个

auto_ptrs拥有同一个对象。

 

那么auto_ptr的copy构造函数和assignment操作符该如何运作呢?

另auto_ptr的copy构造函数和assignment操作符将对象的拥有权交出去!

1     // initialize an auto_ptr with a new object
2     std::auto_ptr<Test> ptr1(new Test("This is the end of the world!"));
3 
4     // copy the auto_ptr
5     // ~ transfers ownership from ptr1 to ptr2
6     std::auto_ptr<Test> ptr2(ptr1);
7 
8     cout<<ptr1->getMsg()<<endl;

上面对象的拥有权从ptr1交到ptr2的时候,再使用ptr1去getMsg的时候,会出现"段错误"提示。

 1 #include <iostream>
 2 #include <string>
 3 #include <memory>
 4 
 5 using namespace std;
 6 
 7 class Test
 8 {
 9     public:
10         Test(const string& psg,const int& id);
11         ~Test();
12         string getMsg();
13     private:
14         string msg;
15         int id;
16 };
17 
18 Test::Test(const string& psg,const int& pid)
19 {
20     msg = psg;
21     id = pid;
22 }
23 
24 Test::~Test()
25 {
26     cout<<"Delete "<<id<<" "<<endl;
27 }
28 
29 string Test::getMsg()
30 {
31     return msg;
32 }
33 
34 int main(void)
35 {
36     std::auto_ptr<Test> ptr1(new Test("This is ptr1",1));
37     std::auto_ptr<Test> ptr2(new Test("This is ptr2",2));
38     ptr2 = ptr1;
39     return 0;
40 }

上面代码的结果是:

1 Delete 2
2 Delete 1

表明: 当ptr2被赋值前正拥有另一个对象,赋值动作发生时会发生delete,将该对象删除。

 

posted on 2014-06-15 22:31  Dream Catcher(DC)  阅读(300)  评论(0编辑  收藏  举报

导航