C++智能指针详解

今天费脑子的东西不想看,我们就谈谈一些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其中存储的指针

第二种:其实和智能指针的实现原理大致相同,智能指针只是用模板的形式封装了一下


智能指针的实现大致原理:

1.智能指针将一个计数器与类指向的对象相关联,引用计数跟踪一共有多少个智能指针共享同一类对象
2.当智能指针对象作为另一对象的副本而创建的时候,也就是拷贝构造时候,拷贝构造函数拷贝指针并增加与之对应的引用计数;
3.当对一个智能指针对象进行值操作的时候,赋值操作符 减少左操作数所指对象的引用计数(若引用计数减为0,则删除该对象),并增加右操作数指向对象的引用计数(因为左侧指针指向了右侧指针指向的对象,所以右侧指针指向的对象的引用计数增加1);

4.调用析构函数时候,减少引用计数(若减为0,则删除基础对象(调用delete));


那么第一种和第二种方式的差别在哪儿呢?

第一种是统一管理的形式,比较粗犷的进行内存释放,主要是为了不内存泄露。但有一点要注意,那就是我们无法确保释放的内存模块没有指针还在引用,释放后指向动态分配的内存的指针绝不能再使用,定时或终止清理之前,一直都会占用内存,造成空间一定程度上的浪费

第二种是一种比较细腻的管理形式,当释放内存时,可以确保已经没有继续引用此内存的指针,且一旦没有引用立即释放内存,可提高系统的资源利用率




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

五癫

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值