zoukankan      html  css  js  c++  java
  • 智能指针之 auto_ptr

      C++的auto_ptr所做的事情,就是动态分配对象以及当对象不再需要时自动执行清理,该智能指针在C++11中已经被弃用,转而由unique_ptr替代,那这次使用和实现,就具体讲一下auto_ptr被弃用的原因,(编译平台:Linux centos 7.0 编译器:gcc 4.8.5 )

      首先使用std::auto_ptr时,需要#include <memory>头文件,具体使用代码如下(文件名:test_ptr.cpp):

    #include <memory>
    #include <iostream>
    
    using namespace std;
    
    class Test
    {
    public:
    	Test()
    	{
    		cout << "construct.." << endl;
    	}
    	
    	~Test()	
    	{
    		cout << "destruct.." << endl;
    	}
    };
    
    void test()
    {
    	
    }
    
    int main()
    {
    	Test* p = new Test(); 
    	auto_ptr<Test> ap(p);
    
    	return 0;
    }

      执行上述代码,我们可以看到,程序结束时,在堆上申请的对象,自动执行了析构函数,将内存释放了

    [root@localhost code]# g++ -g -o autop test_ptr.cpp 
    [root@localhost code]# ./autop
    construct..
    destruct..
    [root@localhost code]#

      具体实现代码如下,构造函数只实现了初始化构造和拷贝构造:

      1 #include <iostream>
      2 
      3 using namespace std;
      4 
      5 template<typename T>
      6 class auto_pt
      7 {
      8 public:
      9     explicit auto_pt(T* p = NULL):m_ptr(p)
     10     {
     11         p = NULL;
     12         cout << "auto_ptr construct" << endl;
     13     }    
     14     
     15     auto_pt(auto_pt& autoPtr):m_ptr(autoPtr.m_ptr)
     16     {
     17         autoPtr.m_ptr = NULL;
     18         cout << "copy auto_ptr construct" << endl;
     19     }
     20 
     21     auto_pt& operator = (auto_pt& p)    
     22     {
     23         if(this != &p)
     24         {
     25             if(m_ptr != NULL)
     26             {
     27                 delete m_ptr;
     28                 m_ptr = p.m_ptr;
     29                 p.m_ptr = NULL;    
     30             }
     31         }
     32         
     33         return *this;
     34     }
     35 
     36     ~auto_pt()
     37     {
     38         if(m_ptr != NULL)
     39         {
     40             cout << "auto_ptr destruct" << endl;
     41             delete m_ptr;
     42             m_ptr = NULL;
     43         }
     44             
     45     }
     46 
     47     T* Get()
     48     {
     49         return m_ptr;
     50     }
     51 
     52     T& operator*()
     53     {
     54         return *m_ptr;
     55     }
     56 
     57     T* operator->()
     58     {
     59         return m_ptr;    
     60     }
     61     
     62 private:
     63     T* m_ptr;
     64 };
     65 
     66 class Test
     67 {
     68 public:
     69     Test()
     70     {
     71         cout << "construct.." << endl;
     72     }
     73     
     74     ~Test()    
     75     {
     76         cout << "destruct.." << endl;
     77     }
     78     
     79     void method()
     80     {
     81         cout << "welcome Test.." << endl;
     82     }
     83 };
     84 
     85 void f(auto_pt<Test>ap)
     86 {
     87     cout << "funtion f :";
     88     ap->method();
     89 }
     90 
     91 int main()
     92 {
     93     //baseic test
     94     Test* p = new Test();
     95     cout << "address0 [%p]" << p << endl;
     96     auto_pt<Test> ap(p);
     97     
     98     cout << "address1 [%p]" << ap.Get()<< endl;
     99     cout << "address2 [%p]" << &ap << endl;
    100     cout << "address3 [%p]" << &(*ap) << endl;
    101 
    102     ap.Get()->method();
    103     (*ap).method();
    104     ap->method();
    105 
    106     return 0;
    107 }

      打印结果:

     1 [root@localhost code]# g++ -o autop_test test.cpp 
     2 [root@localhost code]# ./autop_test 
     3 construct..
     4 address0 [%p]0xb77010
     5 auto_ptr construct
     6 address1 [%p]0xb77010
     7 address2 [%p]0x7ffe8b25f510
     8 address3 [%p]0xb77010
     9 welcome Test..
    10 welcome Test..
    11 welcome Test..
    12 auto_ptr destruct
    13 destruct..
    14 [root@localhost code]# 

      大概实现就是这样,基本和标准库差不多,除了另外两种类型的构造函数没有加进去

      那在我们使用及实现的过程中,发现这个auto_ptr在使用过程中会有如下风险,因此在C++11中已经不再使用,那在我们开发过程中,也最好不要再使用

    1. 两个auto_ptr指向同一块内存,造成多次释放

    1 //if 2 object point one address, application will die
    2 Test* p1 = new Test();
    3 
    4 auto_pt<Test> ap1(p1);    
    5 auto_pt<Test> ap2(p1);

    2. 复制完成后,会将复制的对象置空,因此不能继续使用

    1 int*p=new int();
    2 auto_pt<int>ap1(p);
    3 auto_pt<int>ap2=ap1;
    4 (*ap1).method();//错误,此时ap1只剩一个null指针在手了

    3. 函数形参使用值传递,会发生拷贝操作,导致ap1对象权限获取不到了

    1 void f(auto_pt<int>ap)
    2 {
    3     (*ap).method();
    4 }
    5  
    6 auto_pt<int>ap1(new int(0));
    7 f(ap1);
    8 (*ap1).method();;//错误,经过f(ap1)函数调用,ap1已经不再拥有任何对象了。
  • 相关阅读:
    econtrol窗体设计器
    脚本引擎注册将要使用的类,属性,方法,函数
    FastReport开发手册
    控制钱箱,客显,打印
    Laravel渴求式加载(比较容易理解理解load与with关系)
    50分钟学会Laravel 50个小技巧(基于laravel5.2,仅供参考)
    日期选择器date、week、time、datetime、datetimelocal类型
    input type=date时,时间数据回填,报错The specified value "2019040418" does not conform to the required format...
    Laravel技巧:使用load、with预加载 区别
    arcengine,C#实现分页打印预览
  • 原文地址:https://www.cnblogs.com/blog-yejy/p/8910071.html
Copyright © 2011-2022 走看看