智能指针shared_ptr

一、 原理 :RAII 资源获取即初始化技术

原理:接受一个申请好的内存地址,构造一个保存在栈上的智能指针对象,当程序退出栈的作用域范围后,由于栈上的变量自动被销毁,智能指针内部保存的内存也就被释放掉了(除非将智能指针保存起来)。

为什么这么6呢?

在传统 C++ 中,『记得』手动释放资源,总不是最佳实践。因为我们很有可能就忘记了去释放资源而导致泄露。所以通常的做法是对于一个对象而言,我们在构造函数的时候申请空间,而在析构函数(在离开作用域时调用)的时候释放空间,也就是我们常说的 RAII 资源获取即初始化技术。

#include <iostream>
#include <memory>
using namespace std;

class CData
{
public:
	CData(int iSize) :m_iSize(iSize)
	{
	}
public:
	int m_iSize;
	static CData* m_CDataModule;
};

CData* CData::m_CDataModule = new CData(19);

bool PtrIsNull()
{
	if(NULL == CData::m_CDataModule)
	{
		return false;
	}
	return true;
}
void TestFunc()
{
	bool bResult = PtrIsNull();
	cout <<"01 CData::m_CDataModule->m_iSize " << CData::m_CDataModule->m_iSize << endl;
	shared_ptr<CData> shPtrA(CData::m_CDataModule);
}
int main()
{
	TestFunc();
	bool bResult = PtrIsNull();
	cout << "02 CData::m_CDataModule->m_iSize " << CData::m_CDataModule->m_iSize << endl;
	int iCount = 0;
	
	cin.get();
	return 0;
}

这是在使用智能指针之前

01 CData::m_CDataModule->m_iSize 19
02 CData::m_CDataModule->m_iSize 19

使用智能指针之后,程序第二次输入杂乱无章的数值,是因为堆空间被释放掉了

01 CData::m_CDataModule->m_iSize 19
02 CData::m_CDataModule->m_iSize -572662307

注意PtrIsNull()返回的是 true,这是因为智能指针对堆空间进行了释放,但是对原来的指针没有进行操作

二、引用计数

引用计数是这样一个技巧,记录同一个实例被引用的次数,当引用次数大于0时可用,等于0时释放内存。引用计数的使用常有两个目的:

  • 简化跟踪堆中(也即C++中new出来的)的对象的过程。一旦一个对象通过调用new被分配出来,记录谁拥有这个对象是很重要的,因为其所有者要负责对它进行delete。但是对象所有者可以有多个,且所有权能够被传递,这就使得内存跟踪变得困难。引用计数可以跟踪对象所有权,并能够自动销毁对象。可以说引用计数是个简单的垃圾回收体系。这也是本文的讨论重点。
  • 节省内存,提高程序运行效率。如何很多对象有相同的值,为这多个相同的值存储多个副本是很浪费空间的,所以最好做法是让左右对象都共享同一个值的实现。C++标准库中string类采取一种称为”写时复制“的技术,使得只有当字符串被修改的时候才创建各自的拷贝,否则可能(标准库允许使用但没强制要求)采用引用计数技术来管理共享对象的多个对象。
#include <iostream>
#include <memory>
using namespace std;

class CData
{
public:
	CData(int iSize) :m_iSize(iSize)
	{
	}
public:
	int m_iSize;
	static CData* m_CDataModule;
};

CData* CData::m_CDataModule = new CData(19);

int main()
{
	shared_ptr<CData> shaPtrCDataA(CData::m_CDataModule);
	shared_ptr<CData>  shaPtrCDataB = shaPtrCDataA;

	cout << "Now Use Count"<< shaPtrCDataB.use_count() << endl;

	shared_ptr<CData>  shaPtrCDataC= shaPtrCDataB;
	cout << "Now Use Count" << shaPtrCDataB.use_count() << endl;

	shaPtrCDataA.reset();
	cout << "Now Use Count" << shaPtrCDataB.use_count() << endl;
	cin.get();
	return 0;
}

输出如下:

Now Use Count2
Now Use Count3
Now Use Count2
在这里reset执行一次,引用次数就少一次

发布了195 篇原创文章 · 获赞 41 · 访问量 12万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章