C++11学习笔记 -- 智能指针

#include <memory>
#include <iostream>


/************************************************************************************
使用智能指针的注意点:
	1. 绝对不要自己手动管理堆空间(delete、delete[])
	2. 初始化智能指针时尽可能使用 std::make_shared 空间更小
	  (下面为了学习不用这种方式创建shared_ptr)
	3. 不要用一个裸指针去构造两个独立的智能指针对象(裸指针构造的对象引用计数不关联),
	   只有用智能指针去初始化另一个智能指针时,引用计数才加 1
	4. 用weak_ptr打破shared_ptr的循环引用(如:下边的Father和Son会造成内存泄漏)
	5. 在类内部接口中需要通过this来使用智能指针时,需要继承enable_shared_from_this
	6. 在构造和析构时不能使用shared_from_this()函数
	7. 智能指针实际是模板类,比裸指针效率更低,且更占内存
	8. 优先使用类的实例,实在需要用到指针再考虑智能指针
	  (singleton/object > unique_ptr > shared_ptr)
************************************************************************************/


using namespace std;

//类的前置声明
class Son;
//C++11 using定义类型别名
using Son_sPtr = shared_ptr<Son>;

class Duaghter;
using Duaghter_wPtr = weak_ptr<Duaghter>;
using Duaghter_sPtr = shared_ptr<Duaghter>;

class Father;
using Father_sPtr = shared_ptr<Father>;
using Father_uPtr = unique_ptr<Father>;

//继承自enable_shared_from_this<Father>时,Father成员内部才允许用this构造share_ptr
class Father : public enable_shared_from_this<Father> {
public:
	Father(int id):m_id(id) { cout << "creat Father" << m_id << endl; }
	~Father() { cout << "destory Father" << m_id << endl; }

	void setSon(Son_sPtr& son) { m_son = son; }
	void setDuaghter(Duaghter_sPtr& duaghter) { m_duaghter = duaghter; }
	int ID() { return m_id; }

private:
	Son_sPtr m_son{ nullptr };
	Duaghter_wPtr m_duaghter;//不能给nullptr 因为weak_ptr只能由对应的shared_ptr进行初始化
	int m_id{ 0 };
};

class Son {
public:
	Son(int id):m_id(id) { cout << "creat Son" << m_id << endl; }
	~Son() { cout << "destory Son" << m_id << endl; }

	void setFather(Father_sPtr& father) { m_father = father; }
	int ID() { return m_id; }

private:
	Father_sPtr m_father{ nullptr };
	int m_id{ 0 };
};

class Duaghter {
public:
	Duaghter(int id) :m_id(id) { cout << "creat Duaghter" << m_id << endl; }
	~Duaghter() { cout << "destory Duaghter" << m_id << endl; }

	void setFather(Father_sPtr& father) { m_father = father; }
	int ID() { return m_id; }

private:
	Father_sPtr m_father{ nullptr };
	int m_id{ 0 };
};

void useSharedPtr()
{
	//错误!不能使用两个不相关的智能指针对象管理同一份内存
	//Son *s_son = new Son(1);//裸指针
	//Son_sPtr s2_son(s_son);
	//Son_sPtr s3_son(s_son);
	//cout << "s2_son use_count : " << s2_son.use_count() << endl;
	//cout << "s3_son use_count : " << s3_son.use_count() << endl;

	//shared_ptr的构造函数
	Son_sPtr son(new Son(1));
	//智能指针son这个对象管理的内容被引用的次数 use_count()
	cout << "son use_count : " << son.use_count() << ",id : " << son->ID() << endl;
	//shared_ptr的拷贝构造函数
	Son_sPtr son2(son);
	cout << "son2 use_count : " << son2.use_count() << ",id : " << son2->ID() << endl;
	Son_sPtr son3 = son;
	cout << "son3 use_count : " << son3.use_count() << ",id : " << son3->ID() << endl;
	///重置智能指针;
	//无参数:引用计数-1,当前智能指针被置nullptr
	son3.reset();
	cout << "son use_count : " << son.use_count() << endl;
	///重载了bool
	if(son3)
		cout << "son3 != nullptr" << endl;
	else
		cout << "son3 == nullptr" << endl;
	//有参数:引用计数-1,当前智能指针管理其他的对象
	son2.reset(new Son(2));
	cout << "son use_count : " << son.use_count() << ",id : " << son->ID() << endl;
	cout << "son2 use_count : " << son2.use_count() << ",id : " << son2->ID() << endl;
	son2 = son;
	cout << "son use_count : " << son.use_count() << ",id : " << son->ID() << endl;
	cout << "son2 use_count : " << son2.use_count() << ",id : " << son2->ID() << endl;
	///判断智能指针管理的对象当前是否只有这1个地方再管理unique()
	if (son2.unique())
		cout << "son2 use_count : 1, id : " << son2->ID() << endl;
	else
		cout << "son2 use_count : " << son2.use_count() << ",id : " << son2->ID() << endl;
	///拿智能指针内部管理的对象,不交出管理权
	auto *contain = son.get();
	cout << "son use_count : " << son.use_count() << ",id : " << son->ID() << endl;
	//delete contain;//error ! 不可以自己去删除shared_ptr智能指针管理的对象
//	cout << "son  == nullptr : " << (son == nullptr) << endl;
}

//此时shared_ptr会出现内存泄漏
void testSharedPtr()
{
	Son_sPtr son(new Son(1));
	Father_sPtr father(new Father(1));
	son->setFather(father);//引用基数+1
	father->setSon(son);//引用基数+1
}

void useWeakPtr()
{
	Duaghter_sPtr sDuaghter(new Duaghter(1));
	Duaghter_wPtr wDuaghter;
	///判断weak_ptr是否过期
	if (wDuaghter.expired())
		cout << "wDuaghter is expired !" << endl;
	Duaghter_wPtr wDuaghter2(sDuaghter);
	if (wDuaghter2.expired())
		cout << "wDuaghter2 is expired !" << endl;
	else
		cout << "wDuaghter2 is not expired !" << endl;
	//赋值运算符
	wDuaghter = wDuaghter2;//weak_ptr引用基数+1
	Duaghter_sPtr sDuaghter2 = wDuaghter.lock();//shared_ptr的引用计数+1
	cout << "wDuaghter use_count: " << wDuaghter.use_count() << endl;
	cout << "sDuaghter use_count: " << sDuaghter.use_count() << endl;

	cout << "**************************************" << endl;
	//智能指针sDuaghter不再管理对象
	sDuaghter.reset();
	if (wDuaghter2.expired())
		cout << "wDuaghter2 is expired !" << endl;
	else
		cout << "wDuaghter2 is not expired !" << endl;
	sDuaghter2.reset();
	Duaghter_sPtr sDuaghter3 = wDuaghter2.lock();//此时weak_ptr已过期,取回的是nullptr
	if (!sDuaghter3)
	{
		cout << "wDuaghter3 is null !" << endl;
	}
}

//此时不会出现泄漏问题
void testSharedAndWeakPtr()
{
	Duaghter_sPtr duaghter(new Duaghter(1));
	Father_sPtr father(new Father(1));
	duaghter->setFather(father);
	father->setDuaghter(duaghter);
}

//使用unique_ptr指针作为函数形参
void useUniquePtrParam(Father_uPtr father)
{
	cout << "ID :" << father->ID() << endl;
}

//默认使用unique_ptr管理指针,除非需要共享
void testUniquePtr()
{
	//构造函数
	Father_uPtr father(new Father(1));
	cout << "ID :" << father->ID() << endl;
	cout << "ID :" << (*father).ID() << endl;
	//由于unique_ptr独占特性,所以不存在拷贝构造和赋值运算符
	//可以通过release函数交出管理权和内容
	Father* father2 = father.release();
	cout << "ID :" << father2->ID() << endl;
	if (!father)
	{
		cout << "father is null " << endl;
	}
	delete father2;//销毁原来的内存
	father2 = nullptr;

	Father_uPtr father3(new Father(3));
	//不允许值传递
	//useUniquePtrParam(father3);//编译不过
	//但允许使用右值move传参
	useUniquePtrParam(move(father3));
	if (!father3)//move结束后,智能指针对象变成为初始状态
	{
		cout << "father3 is null " << endl;
	}

	//可以用release或move使unique_ptr交出独占权,从而转换为shared_ptr
	Father_uPtr father4(new Father(4));
	Father_sPtr contain(father4.release());
	cout << "father4 ID: " << contain->ID() << endl;
	Father_uPtr father5(new Father(5));
	Father_sPtr contain2(move(father5));
	cout << "father5 ID: " << contain2->ID() << endl;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值