C/C++语言篇:4种智能指针

本文介绍了C++中的四种智能指针:auto_ptr(已被弃用),unique_ptr(独占式,不支持拷贝),shared_ptr(共享式,具有引用计数),以及weak_ptr(辅助共享指针,解决循环引用问题)。通过智能指针,可以更好地管理动态内存,防止内存泄露。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C++中主要用New和Delete来分配和释放内存,但是有时候我们常常忘记Delete而造成内存泄露。为了避免这个问题,C++引入了智能指针模板类来管理动态内存。C++中智能指针有四种:auto_ptr,unique_ptr、share_ptr、weak_ptr。

1、auto_ptr(C++98的方案,C++11已放弃)
  • auto_ptr要求对它拥有的指针完全占用,两个auto_ptr不能同时拥有同一个普通指针
  • 例如:
auto_ptr<string> p1(new string("hello"));
auto_ptr<sting> p2;
p2 = p1;	//不会报错,但是p2会剥夺p1的拥有权
std::cout << *p1 << std::endl; //报错
  • 由于auto_ptr复制时会剥夺原来指针的拥有权,导致原来的指针失效,再操作原来的指针时会出错,所以C++11中已经不再使用auto_ptr。
2、unique_ptr(替换auto_ptr)
  • unique_ptr同样是独占式占有指针,为了保证安全,它不允许普通的拷贝和复制,保证了同一时间只有一个智能指针指向该对象;所以当unique_ptr被销毁时,他指向的对象也会被销毁。
  • 当我们定义一个unique_ptr时,需要使用new来为其直接初始化。
3、share_ptr
  • share_ptr是共享式智能指针,允许多个智能指针指向同一个对象;
  • 默认创建的share_ptr是一个空指针,可以用new和make_ptr初始化,但是不能直接初始化;例如:
	share_ptr<int> p1(new int(3));	//正确
	share_ptr<int> p2 = make_ptr<int>(4);//正确
	share_ptr<int> p3 = new int(5);	//错误
  • 每个share_ptr都有一个关联的引用计数器。当我们拷贝一个share_ptr时引用计数会递增;当我们给它赋新值或销毁它时,引用计数会递减。
  • 当引用计数减为0时,share_ptr指向的对象会自动销毁,share_ptr指针变为空。
4、weak_ptr
  • weak_ptr是一种弱指针,指向share_ptr指向的对象,不能直接访问对象。
  • weak_ptr只能通过一个share_ptr或另一个weak_ptr对象来构造,它的构造和析构不会引起引用计数的变化。
  • share_ptr可以直接赋值给weak_ptr,weak_ptr可以通过调用lock()函数来获得share_ptr。
  • weak_ptr的引入主要是为了协助share_ptr工作,主要是解决share_ptr相互引用时的死锁问题。
    – 如果说两个share_ptr相互引用,那么这两个指针的引用计数永远都不可能下降为0,资源也就永远不会释放,造成死锁。而将一个share_ptr换成weak_ptr就可以解决死锁问题。例:
class A
{
	share_ptr<B> pb_;
};
class B
{
	share_ptr<A> pa_;
};
void fun()
{
	share_ptr<A> pa(new A());
	share_ptr<B> pb(new B());
	pa->pb_ = pb;
	pb->pa_ = pa;
	cout << pa.use_count() << endl;
	cout << pb.use_count() << endl; 
}
int main()
{
	fun();
	return 0;
}

可以看到fun中pa,pb相互引用,引用计数都是2。跳出fun函数时,pa,pb引用计数减1最终都为1,资源仍然都未被释放(析构函数未被调用)造成死锁。

  • 如果把其中一个类中的share_ptr改成weak_ptr就能解决这个问题。
    我们把类A里的share_ptr pb_改为weak_ptr pb_,这样pb一开始的引用只有1,当fun函数结束时,pa引用计数为1,pb引用计数为0,B资源得到释放,同时又使pa的引用计数减为0,A资源得到释放。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值