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

1.智能指针介绍

智能指针是C++的特性用法,是一个类似指针功能的类对象,其目的是为了更好的管理动态分配的内存,避免出现内存泄漏、悬空指针等问题。C++11的标准库里提供了三种智能指针模板类,分别是std::unique_ptr、std::shared_ptr 和 std::weak_ptr(C++11摒弃了auto_ptr)。

2.为什么需要智能指针

首先来看一段代码

void test(std::string& str)
{
	std::string* ps = new std::string("nihao!\n");
	str = *ps;
	//delete ps;
	return;
}

不难发现代码的隐患问题,每次函数被调用时,ps指针指向的内存空间都分配在堆上,但是在没有delete ps语句的情况下,无论是函数结束还是异常退出,都无法释放内存。然后我们在面对复杂逻辑的编程时,常常会忘记使用delete,这就会导致内存泄漏。
于是我们就会想,如果在函数终止时(不管是正常终止还是异常终止),new出来的内存都像函数内部的局部变量从栈内存上释放那样,从堆上释放,那就很巴适。智能指针的设计就是解决这样的问题。
来看下面这段代码:

void test_auto(std::string& str)
{
	std::unique_ptr<std::string> ps(new std::string("nihaoya!\n"));
	str = *ps;
	return;
}

使用了智能指针模版类后,因为是通过类来管理我们申请的资源,类的析构函数在类对象出作用域的时候会自动被调用,会自动的清理申请的资源。即使没有delete语句,在函数终止时,指针占据的内存空间和指针指向的内存空间都将被释放。

3. 智能指针用法示例

3.1 独占性智能指针std::unique_ptr

所谓的独占型,即两个unique_ptr不能指向同一个对象,指针直接不能复制,只能将所有权通过move接口转移。
看如下一段代码:

std::unique_ptr<std::string>p1(new std::string("hai\n"));	// 1
std::unique_ptr<std::string>p2;								// 2
p2 = p1;													// 3
p2 = move(p1);												// 4
std::cout << *p1 << std::endl;								// 5
std::cout << *p2 << std::endl;								// 6

其中,第三条p2 = p1;是不被允许的,编译系统提示如下。

第5条std::cout << *p1 << std::endl;由于是经过move后,p1指针的内容为空,运行将产生如下报错。
在这里插入图片描述

屏蔽掉报错内容后,系统运行结果如下,将p1指针转移到p2指针,并销毁p1指针内容。
在这里插入图片描述

3.2 共享型智能指针std:: shared_ptr

共享指针shared_ptr是只具有共享所有权语义的智能指针。 每当共享指针shared_ptr的最后一个所有者被销毁时,关联对象都将被删除(或关联资源被清除),允许多个指针指向同一个变量。

3.3 弱引用智能指针std:: weak_ptr

weak_ptr专门为了解决std:: shared_ptr循环引用问题而引入的指针类型,通过shared_ptr构造,配合shared_ptr才能使用,它指向一个由shared_ptr管理的对象而不影响所指对象的生命周期,也就是,将一个weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数。不论是否有weak_ptr指向,一旦最后一个指向对象的shared_ptr被销毁,对象就会被释放。从这个角度看,weak_ptr更像是shared_ptr的一个助手而不是智能指针。
那么,什么是循环引用的问题呢?在shared_ptr的使用过程中,当强引用计数为0是,就会释放所指向的堆内存。那么问题来了,如果和死锁一样,当两个shared_ptr互相引用,那么它们就永远无法被释放了。

3.4 选择智能指针

如果程序需要使用多个指向同一对象的指针,应选择share_ptr,当程序中存在循环调用的逻辑时,选择weak_ptr指针来辅助,反之若不需要多个指针指向同一个对象,则选择unique_ptr。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

>_<!

码字不易,如有帮助,欢迎鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值