智能指针之 auto_ptr

摘要:
=&p)24{25if(m_ptr!=NULL)26{27deletem_ptr;28m_ptr=p.m_ptr;29p.m_ptr=NULL;30}31}3233返回*this;34}3536 ~ auto_ pt()37{38if(m_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已经不再拥有任何对象了。

免责声明:文章转载自《智能指针之 auto_ptr》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇ajax实现文件上传,多文件上传,追加参数2019 云和数据java面试笔试题 (含面试题解析)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

内网esxi磁盘空间不足导致虚拟机宕机

内网esxi磁盘空间不足导致虚拟机宕机 一、问题引入   周一上班的时候,发现公司内网的戴尔服务器上(前人装的ESXi系统,里面有很多个虚拟机),好几个虚拟机异常关机了。点击重新开机,有以下报错提示: 选Retry是没用的,选Cancel,才有可能开机,为啥叫可能,因为有一些空间占用多的虚拟机不一定能开机,会一直重复这种报错。 二、问题研究及解决   检...

ios学习之旅------玩转结构体

1.全局变量和局部变量 局部变量: 概念:定义函数内部变量 定义格式:变量类型 变量名称; 作用域:从定义那一行開始到所在代码块结束 生命周期:从代码运行到定义的哪一行開始,到其所在的代码的结束为止 特点:同样的代码块中不能够有同名的变量 不同的代码块中能够有同名的变量。内部的变量会覆盖外部定义的变量 全局变量: 概念:定义在函数外部变量 定义:变量类型...

集成算法stacking

集成算法--stacking## stacking是什么 stacking是各类算法模型的融合堆叠。假设有四种算法A、B、C、D, 你用A、B、C三种算法,分为对训练集和测试集训练,生成三组被预测了的新的train和test集,然后在用算法D对其训练,最终生成最终的结果。 细解流程:如何生成新的预测了的pred_train。 ①以算法A为例,此时加载...

redis 中文存储乱码问题

在redis 中存储中文,读取会出现乱码(其实不是乱码,只是不是我们存的中文显示) 1 redis> set test "我们" 2 OK 3 redis> get test 4 "xe6x88x91xe4xbbxac" 如何在get时取到它的中文呢?只需要在redis-cli 后面加上--raw redis> get...

第十章 数组和指针

一 数组 数组由一系列相同的元素构成。 告诉编译器需要一个数组的方式叫数组声明(array declaration),声明需要告诉编译器数组元素的个数和类型。  初始化 int main(void) {   int powers[8] = {1,2,4,8,16,32,64,128};  ... } 未初始化的数组元素值为内存中的实际值,此值是不确定...

C++解析(30):关于指针判别、构造异常和模板二义性的疑问

0.目录 1.指针的判别 2.构造中的异常 2.1 如果构造函数中抛出异常会发生什么? 2.2 如果析构函数中抛出异常会发生什么? 3.令人迷惑的写法 3.1 模板中的二义性 3.2 函数异常声明 4.小结 1.指针的判别 面试问题:编写程序判断一个变量是不是指针。 指针的判别:拾遗: C++中仍然支持C语言中的可变参数函数 C...