三种智能指针

这章主要学习智能指针。

  • shared_ptr

1.初始化方式

优先采用make_shared的方式来初始化,因为其更高效。

	int *p = new int();
	std::shared_ptr<int> bptr(p);//方式1 
	std::shared_ptr<int> aptr = std::make_shared<int>(2);//方式 2
	std::shared_ptr<int> cptr(aptr);  //方式3

    //std::shared_ptr<int>p = new int(10);//error,不能这样赋值

2.获取原始指针

	std::shared_ptr<int> p1(new int(10));
	int *ptr = p1.get();//通过get()返回原始指针

3.删除器

	//删除器,针对shared_ptr管理动态数组的时候
	//采用lambda表达式创建个删除int数组的删除器  [](int *p) {delete[]p; }
	std::shared_ptr<int> pArr(new int[10], [](int *p) {delete[]p; });

 4‘注意事项

//error 不能用一个原始指针初始化多个shared_ptr,程序会崩溃
int *p1 = new int(1);
std::shared_ptr<int> pp(p1);
std::shared_ptr<int> pp1(p1);

//ok   shared_ptr允许多个指针指向同一个对象
std::shared_ptr<A> sp1(new A());
std::shared_ptr<A> sp2 = sp1;
	

class A
{
public:
	std::shared_ptr<A> GetSelf()
	{
		return std::shared_ptr<A>(this);
	}
	~A()
	{
		std::cout << "ss" << std::endl;
	}
};
std::shared_ptr<A> sp2 = sp1->GetSelf();	//error  一个this指向两个对象sp1和sp2,return的this会导致重复析构


//用enable_shared_from_this来解决shared_ptr返回this指针的问题
class A :public std::enable_shared_from_this<A>
{
public:
	std::shared_ptr<A> GetSelf()
	{
		return shared_from_this();
	}
	~A()
	{
		std::cout << "ss" << std::endl;
	}
};

use_count()函数用来记录有多少个shared_ptr指向某个开辟的对象
  • unique_ptr
	//unique_ptr是独占性指针,不允许有多个指针对象指向一个地址空间
    //使用move函数就可以了
	std::unique_ptr<int> uptr(new int());
	std::unique_ptr<int> uptr1 = uptr;//error
    std::unique_ptr<int> uptr2 = std::move(uptr);//ok

unique_ptr和shared_ptr相比,其具有以下两个特点

	//unique_ptr可以指向数组,而shared_ptr不可以
	//std::unique_ptr<int[]> pArr(new int[10]);//ok
	std::shared_ptr<int[]>pArr1(new int[10]);//error

	//删除器不同
	std::shared_ptr<int>pShare(new int[2], [](int *p) {delete[]p; });//ok
	//std::unique_ptr<int>pUni(new int[2], [](int *p) {delete[] p; });//error
	//unique_ptr删除器在使用时需确定删除器的类型
	std::unique_ptr<int, std::function<void(int*)>>pUni(new int[2], [](int *p) {delete[] p; });//ok
  • weak_ptr

1.weak_ptr不会是引用计数加1,不管理shared_ptr,其相当于shared_ptr的助手,用来监控shared_ptr

std::weak_ptr<int> g_w;
void func()
{
	if (g_w.expired())
	{
	std::cout << "no shared_ptr" << std::endl;
	}
	else
	{
		auto sp = g_w.lock();
		std::cout << "is " << *sp << std::endl;
	}
}
std::shared_ptr<int>pp1(new int());
std::weak_ptr<int>pw(pp1);
std::cout << "pp1 = " << pp1.use_count() << std::endl;//等于1

//expired来监控资源是否释放
//lock来获取所监控的shared_ptr
{
	std::shared_ptr<int> pp2 = std::make_shared<int>(9);
	g_w = pp2;
	func();
}
func();

//输出结果为:
//is 9
//no shared_ptr

2.weak_ptr用来解决循环引用

class B;
class C;

class B
{
public:
	std::shared_ptr<C> cptr;
	~B()
	{
		std::cout << "B is deleted" << std::endl;
	}
};

class C
{
	public:
		std::weak_ptr<B> bptr;//ok,会走到两个析构函数中,打印输出
		//std::shared_ptr<B> bptr;//error,不会走到两个析构函数
		~C()
		{
			std::cout << "C is deleted" << std::endl;
		}
};

main.cpp

std::shared_ptr<B> bp(new B);
std::shared_ptr<C> cp(new C);
bp->cptr = cp;
cp->bptr = bp;
std::cout << bp.use_count() << std::endl;//都采用shared_ptr时输出2,离开作用域之后变为1,其还是无法删除指针,导致内存泄露

因为weak_ptr本身不会使引用计数加1,即此时bptr仍是1,离开作用于之后,其值减1变为0,B被析构。B析构后其内部的cptr计数减1,离开作用域后cptr技术再减1变为0,C也被析构。

完整调试程序

#include <iostream>
#include <memory>
#include <functional>

std::weak_ptr<int> g_w;
void func()
{
	if (g_w.expired())
	{
	std::cout << "no shared_ptr" << std::endl;
	}
	else
	{
		auto sp = g_w.lock();
		std::cout << "is " << *sp << std::endl;
	}
}
//class A
//{
//public:
//	std::shared_ptr<A> GetSelf()
//	{
//		return std::shared_ptr<A>(this);
//	}
//	~A()
//	{
//		std::cout << "ss" << std::endl;
//	}
//};

//用enable_shared_from_this来解决shared_ptr返回this指针的问题
class A :public std::enable_shared_from_this<A>
{
public:
	std::shared_ptr<A> GetSelf()
	{
		return shared_from_this();
	}
	~A()
	{
		std::cout << "ss" << std::endl;
	}
};
class B;
class C;

class B
{
public:
	std::shared_ptr<C> cptr;
	~B()
	{
		std::cout << "B is deleted" << std::endl;
	}
};

class C
{
	public:
		std::weak_ptr<B> bptr;
		//std::shared_ptr<B> bptr;
		~C()
		{
			std::cout << "C is deleted" << std::endl;
		}
};


int main()
{
	//std::shared_ptr<int>p = new int(10);//error,不能这样赋值
	//std::shared_ptr<int> p1(new int(10));
	//int *ptr = p1.get();//通过get()返回原始指针

	int *p = new int();
	std::shared_ptr<int> bptr(p);//方式1 
	std::shared_ptr<int> aptr = std::make_shared<int>(2);//方式 2
	std::shared_ptr<int> cptr(aptr);  //方式3
	

	//删除器,针对shared_ptr管理动态数组的时候
	//采用lambda表达式创建个删除int数组的删除器  [](int *p) {delete[]p; }
	std::shared_ptr<int> pArr(new int[10], [](int *p) {delete[]p; });

	//error 不能用一个原始指针初始化多个shared_ptr,程序会崩溃
	//int *p1 = new int(1);
	//std::shared_ptr<int> pp(p1);
	//std::shared_ptr<int> pp1(p1);

	//shared_ptr允许多个指针指向同一个对象
	std::shared_ptr<A> sp1(new A());
	std::shared_ptr<A> sp2 = sp1;
	
	std::shared_ptr<A> sp3 = sp1->GetSelf();	//error  一个this指向两个对象sp1和sp2,return的this会导致重复析构

	//use_count()函数用来记录有多少个shared_ptr指向某个开辟的对象
	//{
		std::shared_ptr<B> bp(new B);
		std::shared_ptr<C> cp(new C);
		bp->cptr = cp;
		cp->bptr = bp;
		std::cout << bp.use_count() << std::endl;//都采用shared_ptr时输出2
	//}

	//unique_ptr是独占性指针,不允许有多个指针对象指向一个地址空间
	//std::unique_ptr<int> uptr(new int());
	//std::unique_ptr<int> uptr1 = uptr;//error

	//unique_ptr可以指向数组,而shared_ptr不可以
	//std::unique_ptr<int[]> pArr(new int[10]);//ok
	//std::shared_ptr<int[]>pArr1(new int[10]);//error

	//删除器不同
	std::shared_ptr<int>pShare(new int[2], [](int *p) {delete[]p; });//ok
	//std::unique_ptr<int>pUni(new int[2], [](int *p) {delete[] p; });//error
	//unique_ptr删除器在使用时需确定删除器的类型
	std::unique_ptr<int, std::function<void(int*)>>pUni(new int[2], [](int *p) {delete[] p; });//ok

	//weak_ptr不会是引用计数加1,不管理shared_ptr,其相当于shared_ptr的助手,用来监控shared_ptr
	std::shared_ptr<int>pp1(new int());
	std::weak_ptr<int>pw(pp1);
	std::cout << "pp1 = " << pp1.use_count() << std::endl;//等于1

	//expired来监控资源是否释放
	//lock来获取所监控的shared_ptr
	{
		std::shared_ptr<int> pp2 = std::make_shared<int>(9);
		g_w = pp2;
		func();
	}
	func();
	return 0;
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值