IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++智能指针 -> 正文阅读

[C++知识库]C++智能指针

C++智能指针

智能指针是c++标准程序库中所提供的一种更为安全的使用堆内存的一种方式



前言

我们都知道,C++在使用中,new、delete操作堆内存。但是,对于堆内存,需要由程序员自行进行管理。这就意味着,new出来的堆内存,需要通过程序员手动使用delete进行释放。在实际项目中,程序员往往会犯两种错误,一种是忘记delete,释放内存,导致内存泄漏;还要一种,就是delete两次,会产生引用非法内存的指针。

智能指针的出现,是为了方便储层许愿进行堆内存的管理,防止以上两种错误。这对于编程人员来说,是一种非常方便的使用方式。智能指针是c++11引入的一种行为类似指针,但是可以自动释放指向对象的一种工具。

一、智能指针的原理

1 RALL

RAII 是 resource acquisition is initialization 的缩写(“资源获取即初始化”)。
这种机制的核心思想是,将资源的使用和对象的生命周期进行绑定。对象在初始化时,进行资源分配,对象在销毁时,进行资源释放。

2 原理

智能指针利用RALL技术(资源获取即初始化)堆普通指针进行封装。利用这种封装和操作符重载会令智能指针的使用和指针类似,但实际是一个对象。

二、分类

我们经常使用的智能指针,基本分成三个类型,shared_ptr、unique_ptr、weak_ptr。
下面将会分开介绍这三种不同的智能指针

1.shared_ptr

shared_ptr 实现多个智能指针指向相同对象,该对象和其相关资源会在“最后一个引用被销毁”时候释放。它使用引用计数法进行计数,当对象增加时,引用计数+1, 当对象减少时,引用计数-1。

代码如下(示例):

int main()
{
	string *s1 = new string("s1");
	// 初始化方式有两种;
	//第一种是使用智能指针包装普通指针
	shared_ptr<string> ps1(s1);
	//第二种是使用操作符重载进行类似赋值操作
	shared_ptr<string> ps2;
	ps2 = ps1;
	
	// ps1和ps2都会创建出指向s1的智能指针对象,use_count()会返回目前的引用计数个数。
	cout << ps1.use_count()<<endl;	//2
	cout<<ps2.use_count()<<endl;	//2
	cout << ps1.unique()<<endl;	//0

	string *s3 = new string("s3");
	shared_ptr<string> ps3(s3);

	// get()方法返回智能指针封装的指针。
	cout << (ps1.get()) << endl;	//033AEB48
	cout << ps3.get() << endl;	//033B2C50
	swap(ps1, ps3);	//交换所拥有的对象
	cout << (ps1.get())<<endl;	//033B2C50
	cout << ps3.get() << endl;	//033AEB48

	cout << ps1.use_count()<<endl;	//1
	cout << ps2.use_count() << endl;	//2
	ps2 = ps1;
	cout << ps1.use_count()<<endl;	//2
	cout << ps2.use_count() << endl;	//2
	ps1.reset();	//放弃ps1的拥有权,引用计数的减少
	cout << ps1.use_count()<<endl;	//0
	cout << ps2.use_count()<<endl;	//1
}

2.weak_ptr

shared_ptr在使用中,有一种情况,无法进行解决,就是当两个对象相互使用一个shared_ptr成员变量指向对方,会造成循环引用,使引用计数失效,从而导致内存泄漏。

代码如下:

class B;	//声明
class A
{
public:
	shared_ptr<B> pb_;
	~A()
	{
		cout << "A delete" << endl;
	}
};

class B
{
public:
	shared_ptr<A> pa_;
	~B()
	{
		cout << "B delete" << endl;
	}
};

void fun()
{
	shared_ptr<B> pb(new B());
	shared_ptr<A> pa(new A());
	cout << pb.use_count() << endl;	//1
	cout << pa.use_count() << endl;	//1
	pb->pa_ = pa;
	pa->pb_ = pb;
	cout << pb.use_count() << endl;	//2
	cout << pa.use_count() << endl;	//2
}

int main()
{
	fun();
	return 0;
}

可以看到,class A和class B 互相在成员变量中使用shared_ptr引用了对方。在fun函数跳出时,pa和pb进行栈释放。引用计数-1;但是,pa->pb_以及pb->pa_却没有办法进行释放,这是因为A和B的析构函数没有进行调用,这就导致shared_ptr的引用计数仍旧为1,导致内存泄漏。这就需要引入weak_ptr。

weak_ptr 是一种不控制对象生命周期的智能指针,它是一种弱引入,不增加或减少引用计数。它的出现就是为了解决两个类相互引用时shared_ptr无法进行对象销毁的问题。它和shared_ptr可以进行相互转换。

关于weak_ptr,我们需要注意的是,它么有*和->的操作符重载,我们不能直接进行使用,而是要使用lock()方法转换成shared_ptr,才能进行使用。

shared_ptr<B> p = pa->pb_.lock();

3.unique_ptr

unique_ptr从名字上来看,它持对对象享有独占权利,所以,它不能进行赋值,智能进行移动操作。而当进行移动时,也意味着它的生命周期结束,则将进行销毁。

代码如下:

unique_ptr<int>p1(new int(5));
unique_ptr<int>p2 = p1;// 编译会出错
unique_ptr<int>p3 = move(p1);// 转移所有权, 现在那块内存归p3所有, p1成为无效的针.
p3.reset();//释放内存.
p1.reset();//无效
// swap交换指向的指针
unique_ptr<int>p4(new int(4));
unique_ptr<int>p5(new int(5));
p4.swap(p5);
cout << *p4 << endl; //5
cout << *p5 << endl; //4
// release会将指向的指针释放出去,并不会销毁该对象
unique_ptr<int> auto_pointer (new int);
int * manual_pointer;
*auto_pointer=10;
manual_pointer = auto_pointer.release();
// (auto_pointer is now empty)
cout << "manual_pointer points to " << *manual_pointer << endl; // 10
delete manual_pointer;

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-03-31 23:45:54  更:2022-03-31 23:49:28 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 2:55:50-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码