• 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,将该对象删除。

  • 相关阅读:
    Centos 卸载openjdk
    Hadoop安装之Hive集成与mysql安装
    Hadoop安装-Spark Windows 环境 pycharm开发环境搭建
    Hadoop安装—Spark安装
    Hadoop安装-伪分布式
    Hadoop安装之JDK在Centos虚拟机中安装
    SQL server 数据库调用远程数据库存储过程的实现方法
    以梦为马,铸就美好人生
    kettle实战演练——批量解压有密码的rar文件,并生成xml文件
    Linux diff命令
  • 原文地址:https://www.cnblogs.com/jiangheng/p/3790060.html
Copyright © 2020-2023  润新知