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会删除其所指向的对象,所以这个对象绝对不能被其他对象同时"拥有"。
绝对不可以出现