【C++航海王:追寻罗杰的编程之路】智能指针

07-17 1646阅读

目录

1 -> 为什么需要智能指针?

2 -> 内存泄漏

2.1 ->什么是内存泄漏,以及内存泄漏的危害

2.2 -> 内存泄漏分类

2.3 -> 如何避免内存泄漏

3 -> 智能指针的使用及原理

3.1 -> RAII

3.2 -> 智能指针的原理

3.3 -> std::auto_ptr

3.4 -> std::unique_ptr

3.5 -> std::shared_ptr

4 -> C++11和boost中智能指针的关系


【C++航海王:追寻罗杰的编程之路】智能指针

1 -> 为什么需要智能指针?

先分析下面这段程序有没有什么内存方面的问题?

#define _CRT_SECURE_NO_WARNINGS 1
#include 
using namespace std;
int div()
{
	int a, b;
	cin >> a >> b;
	if (b == 0)
		throw invalid_argument("除0错误");
	return a / b;
}
void Func()
{
	// 1、如果p1这里new 抛异常会如何?
	// 2、如果p2这里new 抛异常会如何?
	// 3、如果div调用这里又会抛异常会如何?
	int* p1 = new int;
	int* p2 = new int;
	cout  如何避免内存泄漏 
  1. 工程前期良好的设计规范,养成良好的编码规范,申请的内存空间记得释放。ps:这个是理想状态。但是如果碰上异常时,就算注意释放了,还是可能会出问题。需要下一条智能指针来管理才有保证。
  2. 采用RAII思想或者智能指针来管理资源。
  3. 有些公司内部规范使用内部实现的私有内存管理库。这套库自带内存泄漏检测的功能选项。
  4. 出问题了使用内存泄漏工具检测。ps:不过很多工具都不靠谱,或者收费昂贵。

总结:

内存泄漏非常常见,解决方案分为两种:

  1. 事前预防型。如智能指针等;
  2. 事后查错型。如泄漏检测工具。

3 -> 智能指针的使用及原理

3.1 -> RAII

RAII(Resource Acquisition Is Initialization)是一种利用对象生命周期来控制程序资源(如内存、文件句柄、网络连接、互斥量等等)的简单技术。

在对象构造时获取资源,接着控制对资源的访问使之在对象的生命周期内始终保持有效,最后在对象析构的时候释放资源。借此,实际上把管理一份资源的责任托管给了一个对象。这种做法有两大好处:

  • 不需要显式地释放资源。
  • 采用这种方式,对象所需的资源在其生命周期内始终保持有效。
    // 使用RAII思想设计的SmartPtr类
    template
    class SmartPtr {
    public:
    	SmartPtr(T* ptr = nullptr)
    		: _ptr(ptr)
    	{}
    	~SmartPtr()
    	{
    		if (_ptr)
    			delete _ptr;
    	}
    private:
    	T* _ptr;
    };
    int div()
    {
    	int a, b;
    	cin >> a >> b;
    	if (b == 0)
    		throw invalid_argument("除0错误");
    	return a / b;
    }
    void Func()
    {
    	SmartPtr sp1(new int);
    	SmartPtr sp2(new int);
    	cout () { return _ptr; }
    private:
    	T* _ptr;
    };
    struct Date
    {
    	int _year;
    	int _month;
    	int _day;
    };
    int main()
    {
    	SmartPtr sp1(new int);
    	*sp1 = 10;
    	cout _year = 2018;
    	// 本来应该是sparray->->_year这里语法上为了可读性,省略了一个->
    	sparray->_year = 2018;
    	sparray->_month = 1;
    	sparray->_day = 1;
    }

    总结一下智能指针的原理:

    1. RAII特性
    2. 重载operator*和operator->,具有像指针一样的行为。

    3.3 -> std::auto_ptr

    【C++航海王:追寻罗杰的编程之路】智能指针

     std::auto_ptr文档介绍

    C++98版本的库中就提供了auto_ptr的智能指针。下面演示auto_ptr的使用及问题。

    auto_ptr的实现原理:管理权转移的思想,下面简化模拟实现了一份fyd::auto_ptr来了解它的原理。  

    // C++98 管理权转移 auto_ptr
    namespace fyd
    {
    	template
    	class auto_ptr
    	{
    	public:
    		auto_ptr(T* ptr)
    			:_ptr(ptr)
    		{}
    		auto_ptr(auto_ptr& sp)
    			:_ptr(sp._ptr)
    		{
    			// 管理权转移
    			sp._ptr = nullptr;
    		}
    		auto_ptr& operator=(auto_ptr& ap)
    		{
    			// 检测是否为自己给自己赋值
    			if (this != &ap)
    			{
    				// 释放当前对象中资源
    				if (_ptr)
    					delete _ptr;
    				// 转移ap中资源到当前对象中
    				_ptr = ap._ptr;
    				ap._ptr = NULL;
    			}
    			return *this;
    		}
    		~auto_ptr()
    		{
    			if (_ptr)
    			{
    				cout ()
    		{
    			return _ptr;
    		}
    		T* get() const
    		{
    			return _ptr;
    		}
    	private:
    		T* _ptr;
    		int* _pRefCount;
    		mutex* _pmtx;
    	};
    	// 简化版本的weak_ptr实现
    	template
    	class weak_ptr
    	{
    	public:
    		weak_ptr()
    			:_ptr(nullptr)
    		{}
    		weak_ptr(const shared_ptr& sp)
    			:_ptr(sp.get())
    		{}
    		weak_ptr& operator=(const shared_ptr& sp)
    		{
    			_ptr = sp.get();
    			return *this;
    		}
    		T& operator*()
    		{
    			return *_ptr;
    		}
    		T* operator->()
    		{
    			return _ptr;
    		}
    	private:
    		T* _ptr;
    	};
    }
    struct Date
    {
    	int _year = 0;
    	int _month = 0;
    	int _day = 0;
    };
    void SharePtrFunc(fyd::shared_ptr& sp, size_t n, mutex& mtx)
    {
    	cout _month++;
    		copy->_day++;
    		}
    	}
    }
    int main()
    {
    	fyd::shared_ptr p(new Date);
    	cout 
VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]