C++ 智能指针的使用 1.auto_ptr

1.普通指针的用法:

// ConsoleApplication2.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
#include <memory>
using namespace std;

class Monster
{
public:
	Monster(){
		cout << "Monster construct\n";
	};
	~Monster(){
		cout << "Monster destruct\n";
	};
	void doSomething(){
		cout << "Monster doSomething\n";
	}
};
int _tmain(int argc, _TCHAR* argv[])
{
	Monster* pMonster = new Monster();// new一块内存
	pMonster->doSomething();
	delete pMonster;// 释放 一块内存,调用monster的析构函数
	pMonster = nullptr;
	return 0;;
}

运算结果:

Monster construct
Monster doSomething
Monster destruct
请按任意键继续. . .

2.std::auto_ptr的用法


#include "stdafx.h"
#include <iostream>
#include <memory>
using namespace std;

class Monster
{
public:
	Monster(){
		cout << "Monster construct\n";
	};
	~Monster(){
		cout << "Monster destruct\n";
	};
	void doSomething(){
		cout << "Monster doSomething\n";
	}
};
int _tmain(int argc, _TCHAR* argv[])
{
	std::auto_ptr<Monster> monster(new Monster);// 使用智能指针,auto_ptr的对象monster在出了作用域之后就会释放,monster在析构时同时会delete成员指针
	monster->doSomething();
	return 0;;
}

运行结果:

Monster construct
Monster doSomething
Monster destruct
请按任意键继续. . .

auto_ptr的缺点:

复制auto_ptr对象时,把指针指传给复制出来的对象,原有对象的指针成员随后重置为nullptr。
这说明auto_ptr是独占性的,不允许多个auto_ptr指向同一个资源。

// ConsoleApplication2.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
#include <memory>
using namespace std;

class Monster
{
public:
	Monster(){
		cout << "Monster construct\n";
	};
	~Monster(){
		cout << "Monster destruct\n";
	};
	void doSomething(){
		cout << "Monster doSomething\n";
	}
};
int _tmain(int argc, _TCHAR* argv[])
{
	std::auto_ptr<Monster> monster(new Monster);// 使用智能指针,auto_ptr的对象monster在出了作用域之后就会释放,monster在析构时同时会delete成员指针
	monster->doSomething();// 怪物做某事
	std::auto_ptr<Monster> monster2 = monster;// 转移指针,此时原指针monster变为空
	monster2->doSomething();// 怪物做某事
	monster->doSomething();// 此时报错,指针已经转移,monster为野指针
	return 0;;
}

运行结果指针赋值后,原来的指针变为nullptr。

这说明auto_ptr是独占性的,不允许多个auto_ptr指向同一个资源。

注意:
虽然本文简单介绍了auto_ptr。
但是不要用auto_ptr! 不要用auto_ptr!

虽然它是c++11以前的最原始的智能指针,但是在c++11中已经被弃用(使用的话会被警告)了。
它的替代品,也就是c++11新智能指针unique_ptr,shared_ptr,weak_ptr将在下文出现

3.auto_ptr的实现写法:

3.1 需求分析

  1. 这个类首先是一个模板类
  2. 这个类的构造函数,参数为一个指针
  3. 这个类有一个指针变量,用来存储构造函数出过来的指针
  4. 这个类支持->操作符
  5. 这个类支持*操作符
  6. 这个类支持复制操作符
  7. 这个类析构时要delete管理的指针
  8. 这个类在复制时,原来的类对象要释放其管理的指针
    // ConsoleApplication2.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include <iostream>
    #include <memory>
    using namespace std;
    
    class Monster
    {
    public:
    	Monster(){
    		cout << "Monster construct\n";
    	};
    	~Monster(){
    		cout << "Monster destruct\n";
    	};
    	void doSomething(){
    		cout << "Monster doSomething\n";
    	}
    };
    
    template<typename T>
    class aauto_ptr
    {
    public:
    	//使用explicit关键字避免隐式转换
    	explicit aauto_ptr(T* p = 0);
    
    	~aauto_ptr();
    
    	//使用另一个类型兼容的aauto_ptr来初始化一个新的aauto_ptr
    	aauto_ptr(aauto_ptr<T>& rhs);
    
    	aauto_ptr<T>& operator=(aauto_ptr<T>& rhs);
    
    	T& operator*() const;
    	T* operator->() const;
    
    	//返回原始对象的指针
    	T* get() const;
    	//放弃指针的所以权
    	T* release();
    	//删除原有指针并获得指针的p的所有权
    	void reset(T* p = 0);
    
    private:
    	T* pointee;
    
    };
    
    template<typename T>
    aauto_ptr<T>::aauto_ptr(T* p)
    	:pointee(p)
    {}
    
    template<typename T>
    aauto_ptr<T>::aauto_ptr(aauto_ptr<T>& rhs)
    	: pointee(rhs.release())
    {}
    
    template<typename T>
    aauto_ptr<T>::~aauto_ptr()
    {
    	delete pointee;
    }
    
    template<typename T>
    aauto_ptr<T>& aauto_ptr<T>::operator=(aauto_ptr<T>& rhs)
    {
    	if (this != &rhs)
    		reset(rhs.release());
    	return *this;
    }
    
    template<typename T>
    T& aauto_ptr<T>::operator*() const
    {
    	return *pointee;
    }
    
    template<typename T>
    T* aauto_ptr<T>::operator->() const
    {
    	return pointee;
    }
    
    template<typename T>
    T* aauto_ptr<T>::get() const
    {
    	return pointee;
    }
    
    template<typename T>
    T* aauto_ptr<T>::release()
    {
    	T* oldpointee = pointee;
    	pointee = 0;
    	return oldpointee;
    }
    
    template<typename T>
    void aauto_ptr<T>::reset(T* p)
    {
    	if (pointee != p)
    	{
    		delete pointee;
    		pointee = p;
    	}
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	aauto_ptr<Monster> monster(new Monster);
    	monster->doSomething();
    	monster.get()->doSomething();
    	
    	return 0;;
    }
    
    
发布了257 篇原创文章 · 获赞 22 · 访问量 9万+

猜你喜欢

转载自blog.csdn.net/qq_24127015/article/details/104407297