c++第23次课老师代码(智能指针)__2018.06.09

代码:

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

#include "stdafx.h"


/*
C++23次课   智能指针

int *p = new int; 裸指针
裸指针的缺点:
1.必须手动释放资源
2.由于程序逻辑的错误,导致释放资源的代码没有被调用到
3.程序运行过程中,发生异常,导致释放资源的代码没有被调用到

智能指针   智能(不管程序运行发生什么意外的情况,一定会帮用户把资源释放掉)
数据段   堆    栈


所有的智能指针   都需要  考虑怎么解决浅拷贝问题!!!
auto_ptr 最新的auto_ptr智能指针对象引用资源,之前的auto_ptr都失效了


智能指针:
不带引用计数的智能指针(资源没有引用计数)
auto_ptr
scope_ptr
unique_ptr



带引用计数的智能指针(所有的资源都有相应的引用计数)
1.强智能指针   =》   它可以改变资源的引用计数
带引用计数的强智能指针的缺陷:
循环/交叉引用的时候,造成资源无法释放  
怎么解决呢?
      弱智能指针(它不可以改变资源的引用计数)    

shared_ptr和weak_ptr
都是线程安全的  可以直接在多线程环境中使用




*/
#include <iostream>
#include <memory>    // 这个头文件中,包含了C++库所有的智能指针
#include <unordered_map>
using namespace std;

/*
专门用来统计资源的引用计数  void*  int

*/
class ReferenceCount
{
public:
	//给ptr指向的资源增加引用计数
	void incRef(void *ptr)
	{
		refMap[ptr]++;

#if 0
		cout << ptr << endl;
		unordered_map<void*, int>::iterator it = refMap.find(ptr);
		if (it == refMap.end())
		{
			cout << "xxx" << endl;
			refMap.insert(make_pair(ptr, 1));
		}
		else
		{
			++(it->second);
		}
#endif
	}
	//给ptr指向的资源减少引用计数
	int decRef(void *ptr)
	{
		unordered_map<void*, int>::iterator it = refMap.find(ptr);
		if (it == refMap.end())
		{
			return 0;
		}
		else
		{
			int ret = --(it->second);
			if (it->second == 0)
			{
				refMap.erase(it);
			}
			return ret;
		}
	}
private:
	//map的key表示资源地址, value表示资源的引用计数
	unordered_map<void*, int> refMap;
};

template<typename T>
class CSmartPtr
{
public:
	CSmartPtr(T *ptr = NULL)
		:mptr(ptr)
	{
		if (mptr != NULL)
		{
			incRef();
		}
	}
	CSmartPtr(const CSmartPtr<T> &src)
		:mptr(src.mptr)
	{
		if (mptr != NULL)
		{
			incRef();
		}
	}
	CSmartPtr<T>& operator=(const CSmartPtr<T> &src)
	{
		if (this == &src)
			return *this;

		if (decRef() == 0)
		{
			delete mptr;
			mptr = NULL;
		}

		mptr = src.mptr;
		if (mptr != NULL)
		{
			incRef();
		}
		return *this;
	}
	~CSmartPtr()
	{ 
		if (decRef() == 0)
		{
			delete mptr;
			mptr = NULL;
		}
	}

	T& operator*()
	{
		return *mptr;
	}
	const T& operator*()const
	{
		return *mptr;
	}
	T* operator->()
	{
		return mptr;
	}
	T* operator->()const
	{
		return mptr;
	}
private:
	T *mptr;
	//专门供智能指针,查看当前它所引用的资源的引用计数
	static ReferenceCount refCnt;

	void incRef(){ refCnt.incRef(mptr); }
	int decRef(){ return refCnt.decRef(mptr); }
};

template<typename T>
ReferenceCount CSmartPtr<T>::refCnt;

//类的前置声明
class B;
class A
{
public:
	A(){ cout << "A()" << endl; }
	~A(){ cout << "~A()" << endl; }
	void test();
	//资源引用的地方,都采用弱智能指针
	weak_ptr<B> _ptrb;
};
class B
{
public:
	B(){ cout << "B()" << endl; }
	~B(){ cout << "~B()" << endl; }
	void func(){ cout << "call B::func" << endl; }

	//资源引用的地方,都采用弱智能指针
	weak_ptr<A> _ptra;
};


void A::test()
{
	//_ptrb->func(); 
	//那么虽然弱智能指针不会引起资源的引用计数增加,
	//但是它也不能直接访问对象。
	//lock 从弱智能指针   提升  强智能指针
	shared_ptr<B> ptr = _ptrb.lock();
	if (ptr != NULL)
	{
		//就表示提升成功了
		ptr->func();
	}
}

int main()
{
	/*
	生成资源的时候,一定是使用强智能指针
	*/
	shared_ptr<A> ptra(new A());
	shared_ptr<B> ptrb(new B());

	ptra->_ptrb = ptrb;
	ptrb->_ptra = ptra;

	ptra->test();

	return 0;
}




#if 0
int main(int argc, char* argv[])
{
	CSmartPtr<int> ptr1(new int);
	*ptr1 = 30;
	cout << *ptr1 << endl;

	CSmartPtr<int> ptr2(ptr1);
	CSmartPtr<int> ptr3(ptr1);
	ptr2 = ptr3;
	ptr3 = ptr1;


#if 0
	auto_ptr<int> ptr2(new int);
	*ptr2 = 10;
	cout<<*ptr2<<endl;
	auto_ptr<int> ptr3(ptr2);
	*ptr2 = 10;
#endif
	//cout<<*ptr2<<endl;
	//*ptr3 = 20;
	//cout<<*ptr3<<endl;

	return 0;
}

int main(int argc, char* argv[])
{
	CSmartPtr<int> ptr1(new int);
	*ptr1 = 30;
	cout << *ptr1 << endl;

	const CSmartPtr<int> ptr2(new int(40));
	cout << *ptr2 << endl;

	CSmartPtr<A> ptr3(new A());
	(*ptr3).func();

	//ptr3.operator->(func());
	//(ptr3.operator->())->func();
	ptr3->func();

	const CSmartPtr<A> ptr4(new A());
	ptr4->func();

	return 0;
}
#endif
	/*int *p = new int;

	if (xxxx){
		return 0;
	}
	//中间代码抛出异常了

	delete p;*/






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值