智能指针之 auto_ptr

Posted 还在

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了智能指针之 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;
}

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

[[email protected] code]# g++ -g -o autop test_ptr.cpp 
[[email protected] code]# ./autop
construct..
destruct..
[[email protected] 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 [[email protected] code]# g++ -o autop_test test.cpp 
 2 [[email protected] 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 [[email protected] 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已经不再拥有任何对象了。

 

以上是关于智能指针之 auto_ptr的主要内容,如果未能解决你的问题,请参考以下文章

c++11之智能指针

C11新特性之智能指针

c++中的智能指针auto_ptr解析

智能指针分析及auto_ptr源码

智能指针(auto_ptr)vc版

智能指针的模拟实现 auto_ptr scoped_ptr shared_ptr