《白话C++》第10章 STL和boost,Page85 std::shared_ptr常用功能

std::shared_ptr基本用法包括:

(1)取裸指针

//get()成员取回裸指针
std::shared_ptr <int> pa(new int(5));
int* p = pa.get(); /**< 取回裸指针 */

(2)判断是否为空

肯定可以这样写:

std::shared_ptr <int> pa;
if(pa.get() != nullptr)
...

或者更具C++风格的判断指针是否为空:

if(!pa.get())
...

以上都是通过get()取得裸指针,不过shared_ptr(其他智能指针也一样)重载了‘!’ 操作符。

对一个智能指针执行逻辑取反(‘!’)操作,当它所管理的裸指针为空时,返回真:

std::shared_ptr <int> pa;
if(!pa)...

也可以直接拿来和nullptr作相等比较,因为shared_ptr(其他智能指针也一样)重载了和指针的逻辑相等判断(‘==’)操作:

if(pa == nullptr)...

再试试逻辑不等判断操作‘!=’。默认空构造产生的shared_ptr拥有空的裸指针,即拥有一个nullptr。

std::shared_ptr <int> pb;
if(pb == nullptr)  //和nullptr做相等比较
{cout << "pb的裸指针是空指针" << endl;
}

(3)比较操作

两个shared_ptr也可以用来比较,并且编译器能够帮我们杜绝风马牛不相及的比较

cout << "----------test5----------" << endl;
/**< 比较操作 */
std::shared_ptr <int> pi(new int);
std::shared_ptr <int> pi2(pi);//断定pi和pi2相等(所拥有的指针指向相同)
assert(pi2 == pi); //成立std::shared_ptr <char> pc(new char);if(pi == pc) //编译出错

比较pc和pi时,编译就不通过。一个指向int数据的指针,一个指向char数组的指针,二者有什么好比的呢?

为了模拟裸指针间的比较,shared_ptr也提供‘<’、‘>’、‘<=’及‘>=’等大小的比较,以及前面提到的‘==’和‘!=’。

(4)拷贝构造、赋值

std::shared_ptr <int> pa(new int);
std::shared_ptr <int> pb(pa); ///拷贝构造
std::shared_ptr <int> pc(new int);
pc = pb; ///赋值

002行,pb从pa复制并构造时,主要结果一是二者所拥有的裸指针指向同一对象内存 ;二是二者所共有“引用计数”是2。

003行,创建了pc,它拥有自己的裸指针(后成‘原裸指’)。此时它和pa、pb没有关系。

004行,pc改为从pb赋值,它将丢弃‘原裸指’,改为和pa、pb同指向。赋值时,‘原裸指’将被释放(因为没有别的shared_ptr拥有)。

严重危险的情况发生在下面这样的代码中:

int * pi = new int;
/**< 管理着共同的裸指针,而不是共同管理同一个裸指针 */
std::shared_ptr <int> sia(pi); //这没错
std::shared_ptr <int> sib(pi); //这?

sia的构造没有问题,构造之后的智能指针对象sia就托管了裸指针pi所指向的内存(因此后面不应该有delete pi的操作)。

关键是sib的构建,它的构造入参也是裸指针pi,而不是同类sia。这就造成了sia认为:我是第一个管理pi的shared_ptr;然而sib也认为自己是第一个管理pi的shared_ptr。

注意,此时sia和sib的状态是“它们管理着共同的裸指针”,而非我们所要的“它们共同管理同一个裸指针”,此时sia中的引用计数是1,而sib也一样,二者中任何一个结束生命周期,都会去释放pi所指向的内存。

【危险】:同一裸指针,确保从shared_ptr对象开始“分享”

做法很简单:如果你有一个裸指针需要使用shared_ptr管理,就确保一开始只用一个shared_ptr对象在创建时托管该裸指针,然后从第二个shared_ptr开始,就只从之前的shared_ptr拷贝构建。

“不作就不会死”

再看看以下“不作就不会死”的代码:

std::shared_ptr<int> sia(new int);
std::shared_ptr<int> sib(sia.get());

明明已经有一个智能指针sia了,可sib非要从sia身上得到裸指针然后再另立山头管理。

下面的代码犯了类似的问题

struct S2;struct S1
{S1(S2* ptr); ///构造入参是一个S2类型指针std::shared_ptr<S2> ps2;///成员数据
};struct S2
{S2();~S2();S1 * ps1; ///属性
};S1::S1(S2 * ptr): ps2(ptr) ///初始化共享指针ps2, ps2管理着指针ptr
{cout << "调用了S1构造函数,并将入参委托给shared_ptr ps2" << endl;
}
S2::S2()
{cout << "调用了S2构造函数,并以S2自身作为入参构造一个S1" << endl;ps1 = new S1(this);
}S2::~S2()
{delete ps1;
}void bad_test_1()
{S2 s2;  ///s2是一个栈对象,
}void bad_test_2()
{cout << " new一个S2,委托给scoped_ptr " << endl;boost::scoped_ptr <S2> ps2 (new S2);
}

先看bad_test_1(),该函数创建一个S2的栈对象;于是看23行的S2的构造函数,发现它构造了一个S1的堆对象,并且以自身作为指针入参传递给S1的构造函数;继续跟踪,看S1构造函数,关注它取入参(一个指向某S2对象的指针)作什么事。

请看019行,这个指针被用来作为S1的成员数据ps2的构造入参,而ps2是一个share_ptr<S2>。

第一个问题出现了:ps2是一个智能指针,但它却管理了一个并不需要释放的栈对象,即bad_test_1()函数中s2.

bad_test_2()函数中创建的堆对象,已经托管给scoped_ptr <S2>,后面再七传八传最终又一次委托给某个shared_ptr<S2>。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/478073.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

STM32-点亮 LED

目录 1 、电路构成及原理图 2 、编写实现代码 3、代码讲解 4、烧录到开发板调试、验证代码 5、检验效果 本人使用的是朗峰 STM32F103 系列开发板&#xff0c;此笔记基于这款开发板记录。 1 、电路构成及原理图 首先&#xff0c;通过朗峰 F1 开发板 LED 部分原理图看到…

接口频繁请求,被刷爆怎么办

目录 前言 1 防火墙 2 验证码 3 鉴权 4 IP白名单 5 数据加密 6 限流 7 监控 8 网关 前言 在面试时&#xff0c;经常会被问一个问题&#xff1a;如何防止别人恶意刷接口&#xff1f; 这是一个非常有意思的问题&#xff0c;防范措施挺多的。今天这篇文章专门跟大家一起…

css2背景

css2背景 一.背景颜色二.背景图片三.背景平铺四.背景图片位置五.背景图像固定六.复合型写法七.背景颜色半透明八.总结 一.背景颜色 默认是transparent(透明&#xff09; 二.背景图片 默认是none 三.背景平铺 默认是background-repeat(平铺&#xff09; 四.背景图片位置…

Spring Boot应用集成Actuator端点解决未授权访问的漏洞

一、前言 我们知道想要实时监控我们的应用程序的运行状态&#xff0c;比如实时显示一些指标数据&#xff0c;观察每时每刻访问的流量&#xff0c;或者是我们数据库的访问状态等等&#xff0c;需要使用到Actuator组件&#xff0c;但是Actuator有一个访问未授权问题&#xff0c;…

Springboot+vue的疫情信息管理系统(有报告)。Javaee项目,springboot vue前后端分离项目。

演示视频&#xff1a; Springbootvue的疫情信息管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot vue前后端分离项目。 项目介绍&#xff1a; 本文设计了一个基于Springbootvue的前后端分离的疫情信息管理系统&#xff0c;采用M&#xff08;model&a…

计算机专业假期必看5部电影

社交网络The Social Network (2010) 《社交网络》&#xff08;The Social Network&#xff09;根据本麦兹里奇的小说《意外的亿万富翁&#xff1a;Facebook的创立&#xff0c;一个关于性、金钱、天才和背叛的故事》改编而成。由大卫芬奇执导&#xff0c;杰西艾森伯格、安德鲁加…

亚马逊测评-养号技巧大揭秘!必须注意的事项!

众所周知&#xff0c;不论是线上还是线下的互联网电商平台&#xff0c;在被刷单的情况下都存在。举例来说&#xff0c;国内一些知名的线上交易平台&#xff0c;如淘宝、京东、拼多多等&#xff0c;都有商家为了提高店铺排名、星级和转化率等目的&#xff0c;进行刷单业务。同样…

OJ链接——打印从1到最大的n位数

目录 1. 题目描述2. 示例3. 分析思路4. 完整代码 1. 题目描述 输入数字 n&#xff0c;按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3&#xff0c;则打印出 1、2、3 一直到最大的 3 位数 999。 用返回一个整数列表来代替打印n 为正整数&#xff0c;0 < n < 5 链接在…

不同的AI修改同一篇文章标题

提问AI 我写了一篇文章&#xff0c;请帮我把标题重新改一下&#xff1a;“比较不同AI分析同一个错误代码及给出解决方案的能力&#xff08;结果出我意料&#xff09;” 这篇文章的原地址为&#xff1a;https://blog.csdn.net/snans/article/details/136132211 答案对比结果&am…

投资银行在网络安全生态中的作用

文章目录 一、投资银行的含义(一)并购买方。(二)并购卖方。(三)IPO辅助。(四)投资银行业务的另一方面是帮助这些交易融资。二、从投资银行角度看网络安全产业(一)行业的短期前景三、复杂的网络安全并购(一)行业知识对投资银行业务很重要(二)在网络安全领域,技术…

C 语言 ConsoleRogueLike 控制台肉鸽游戏 DEVC++ VS2022都可用

使用 C 语言和 windows 的键盘检测函数和延迟函数&#xff0c;开发的控制台 roguelike 游戏 点开 .exe 文件立即进入游戏 AWSD 移动 J 攻击 K 加成buff 没有结束条件&#xff0c;除非碰到敌人。 其他模块功能还没来得及开发 author : 民用级脑的研发记录 DEVC 项目工程代码副本…

BN介绍:卷积神经网络中的BatchNorm

一、BN介绍 1.原理 在机器学习中让输入的数据之间相关性越少越好&#xff0c;最好输入的每个样本都是均值为0方差为1。在输入神经网络之前可以对数据进行处理让数据消除共线性&#xff0c;但是这样的话输入层的激活层看到的是一个分布良好的数据&#xff0c;但是较深的激活层…