今天费脑子的东西不想看,我们就谈谈一些c++中关于智能指针的知识吧
1.c++中智能指针的介绍
学习c++的人都知道,在c++中,动态内存的管理是通过一对运算符来完成的:new和delete。
new:在动态内存中为对象分配空间并返回一个指向该对象的指针,我们可以选择对对象进行初始化。
delete:接受一个动态对象的指针,销毁该对象,并释放与之关联的内存。
就我个人而言,到目前为止,我都是用上述方式来进行动态内存的管理,刚开始使用时,确实容易这样或者那样的问题:比如内存泄露、在尚有指针引用内存的情况下就释放了它,已故产生引用非法内存的指针等。当然,熟练之后,还是很好用的。动态内存的管理这块既是c++的优势,也是c++的劣势。相比与其他语言所写程序而言,c++程序员所写的程序容易造成系统崩溃(即使编译通过,运行时也可能出问题),或者内存持续泄露导致服务程序越来越慢,最后主机也可能崩溃。但如果动态内存管理用得好,可以有效利用系统资源,使得编程人员具有更大的权限,直接对内存操作,可控性更强
在c++98中,智能指针通过一个模板“auto_ptr”来实现,auto_ptr以对象的方式来管理堆分配的内存,在适当的时间(比如析构),释放所获得的内存。这种内存管理的方式只需要程序员将new操作返回的指针作为auto_ptr的初始值即可,程序员不能显式的调用delete。如 auto_ptr(new int);
这在一定程度上避免了堆内存忘记释放造成的问题。不过auto_ptr也有一些缺点(拷贝是返回一个左值,不能调用delete[]等),所以在c++11中被废弃了。
c++11标准照中改用unique_ptr,share_ptr,及weak_ptr等智能指针自动回收堆分配的对象。新的标准库提供两两种智能指针类型来管理对象(区别在于管理底层指针的方式),shared_ptr允许多个指针指向同一个对象;unique_ptr则"独占”所指向的对象。而weak_ptr是一种指向shared_ptr所管理的对象的弱引用
2.shared_ptr类
第一点:首先大家要注意,智能指针也是模板
第二点:我们可以把智能指针当做普通指针来使用
第三点:我们需要知道标准库函数make_shared。它是shared_ptr独有的操作,是一种最安全的分配和使用动态内存的方法,在动态内存中分配一个对象并初始化它,返回指向此对象的shared_ptr.
//举例说明创建语法
//指向一个值为42的int的shared_ptr
shared_ptr<int> p3 = make_shared<int>(42); (此时p3中的计数器会增1)
//p4指向一个值为"1111111111"的string
shared_ptr<string> p4 = make_shared<string>(10,'1');
每个shared_ptr都有一个关联的计数器,通常称其为引用计数。多拷贝一个shared_ptr,计数器就会增1
shared_ptr的析构函数会递减它所指向的对象的引用计数。如果引用计数变为0,shared_ptr的析构函数就会销毁对象,并释放它所占用的内存。
shared_ptr还可以和new结合使用
注意:一个用来初始化智能指针的普通指针必须指向动态内存,因为智能指针默认使用delete释放它所关联的对象
shared_ptr<int> p1 =new int(100); //错误,内置指针不能隐式转化为智能指针
shared_ptr<int> p1(new int(1024)); //正确
注意:不要混合使用普通指针和智能指针
不要使用get初始化另一个智能指针或为智能指针赋值
暂且不想写了,一些常见的坑或者使用方法去看看c++ primer第五版吧,通熟易懂,实在没什么好讲的
3.智能指针原理解析
对了,还是简要说说智能指针的实现机制(智能指针,听起来好像很高大上,现今技术界,动不动就来个智能,什么智能专家系统,人工智能,其实绝不是我们想象中的智能,能做的都还是很有限,)
先说说我以前没用智能指针的时候是怎么进行动态内存管理的
第一种:一个大项目被分为了好几个模块,分别对应好几个子系统。如果是粗颗粒管理的话,可以对子系统设置一个全局静态的动态内存索引,每次new后的指针加入到此索引中,最后在程序终止函数中或者定期(看需求)遍历索引,delete其中存储的指针
第二种:其实和智能指针的实现原理大致相同,智能指针只是用模板的形式封装了一下
智能指针的实现大致原理:
4.调用析构函数时候,减少引用计数(若减为0,则删除基础对象(调用delete));
第一种是统一管理的形式,比较粗犷的进行内存释放,主要是为了不内存泄露。但有一点要注意,那就是我们无法确保释放的内存模块没有指针还在引用,释放后指向动态分配的内存的指针绝不能再使用,定时或终止清理之前,一直都会占用内存,造成空间一定程度上的浪费
第二种是一种比较细腻的管理形式,当释放内存时,可以确保已经没有继续引用此内存的指针,且一旦没有引用立即释放内存,可提高系统的资源利用率