[c++]实例观察返回值优化

1 返回值优化现象 RVO

如下代码,在 MakeObj() 中创建了一个局部对象 obj,并将 obj 返回。 Test() 函数调用了 MakeObj(),并将 MakeObj() 的返回值赋值给了 obj。

按我们的预期,MakeObj() 是值返回,在 main() 调用 Test() 的过程中,应该发生了两次构造和两次析构。

第一次构造:默认构造,在 MakeObj() 声明局部变量的时候。

第二次构造:拷贝构造,在 MakeObj() 返回的时候,将返回值赋值给 Test() 中的局部变量 obj 时

第一次析构:在函数 Test() 中,MakeObj() 返回值赋值给 Test() 中的 obj 完成时, MakeObj() 中的局部变量析构

第二次析构:在函数 Test() 返回时,Test() 函数中的 obj 析构

#include <iostream>class Obj {
public:Obj(int i) {i_ = i;std::cout << "Obj(), i: " << i_ << ", this: " << this << std::endl;}Obj(const Obj &obj) {i_ = obj.i_;std::cout << "copy constructor, i: " << i_ << ", this: " << this << std::endl;}~Obj() {std::cout << "~Obj(), i: " << i_ << ", this: " << this << std::endl;}int i_;};Obj MakeObj() {int a = 10;Obj obj(1);int b = 10;printf("1, &obj = %p, &a = %p, &b = %p, sizeof(obj) = %d\n", &obj, &a, &b, sizeof(obj));return obj;
}void Test() {printf("before make obj\n");int a = 100;Obj obj = MakeObj();int b = 100;printf("2, &obj = %p, &a = %p, &b = %p\n", &obj, &a, &b);printf("after make obj\n");
}int main() {Test();printf("before main return\n");return 0;
}

编译之后运行,现象与我们预期的并不是一致的。如下图所示,只发生了一次构造和一次析构。

并且在 MakeObj() 和 Test() 中均把 obj 的地址打印出来了,两个对象的地址是一样的。

2 禁用返回值优化:-fno-elide-constructors

g++ 编译的时候,默认开启了返回值优化,如果想要禁用返回值优化,那么在编译时需要带上标志 -fno-elide-constructors。

如下图所示,禁用返回值优化之后,运行过程与我们预期的是一致的。

 

3 局部变量在函数返回的时候没有销毁吗

从上边的实验可以看出,默认情况下,编译器开启了返回值优化。但是从常识来看,函数返回的时候,局部变量(栈空间)要释放,对象会销毁。

那么开启返回值优化的时候,函数返时,难道局部对象没有销毁 ? 

开启返回值优化的时候,并没有违反栈销毁的规律。

从上边的打印结果可以看出来,在函数 MakeObj() 以及 Test() 函数中,局部变量 obj 前后分别定义了局部变量 a 和 b,把 a 和 b 的地址也打印出来了。

局部变量都是保存在栈上,一个函数中的多个局部变量的地址应该是相邻的才对。但是看打印结果,obj 的地址和 MakeObj() 中的 a 和 b 的地址并不是相邻的,而是和 Test() 中的 a 和 b 是相邻的。这就是编译器起的作用,编译器判断变量的生命周期,然后决定将局部变量放在哪个位置。

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

商业智能信息系统(BI):一文扫盲,全面掌握企业经营状况。

大家好&#xff0c;我是大美B端工场&#xff0c;本期继续分享商业智能信息系统的设计&#xff0c;欢迎大家关注&#xff0c;如有B端写系统界面的设计和前端需求&#xff0c;可以联络我们。 一、BI是什么 商业智能&#xff08;Business Intelligence&#xff0c;简称BI&#xf…

c语言经典测试题5

1.题1 t0; while(printf("*")) { t; if (t<3) break; }关于上述代码描述正确的是&#xff1f; A: 其中循环控制表达式与0等价 B: 其中循环控制表达式与0等价 C: 其中循环控制表达式是不合法的 D: 以上说法都不对 我们来分析一下&#xff1a;printf的返回值…

笔记本Win 10系统查看电池健康状况

博主最近换了个笔记本电池&#xff0c;之前的电池容量明显变小了很多&#xff0c;而且出现了轻微鼓包的情况。所以用gpt问了一下怎么用系统的方法查看电池情况。 在Windows 10系统中&#xff0c;您可以通过以下步骤来查看笔记本电脑电池的健康状况&#xff1a; 打开命令提示符&…

ARM服务器部署Kafka集群

安装前必备的条件是: (1)安装jdk(提供环境); (2)安装zookeeper(注册kafka信息); 需要这方面信息的可以查看我之前写的文档; 一.下载安装包 Kafka官网下载地址 Apache Kafka 根据自己需要下载相应的版本 目前最新的版本是3.6.1。 二.解压安装包 服务器上传下载好的kafk…

VSCODE include错误 找不到 stdio.h

解决办法&#xff1a; Ctrl Shift P 打开命令面板&#xff0c; 键入 “Select Intellisense Configuration”&#xff08;下图是因为我在写文章之前已经用过这个命令&#xff0c;所以这个历史记录出现在了第一行&#xff09; 再选择“Use gcc.exe ”&#xff08;后面的Foun…

智慧公厕与智慧驿站:城市未来公共厕所的革命性升级

在当今社会&#xff0c;智慧公厕已经成为城市建设中一个备受关注的话题。智慧公厕究竟是什么&#xff1f;它代表了未来式的公共厕所&#xff0c;在使用方式、服务方式、管理方式、协作方式上均是变革式的升级。随着科技的进步和城市化的发展&#xff0c;智慧公厕的未来发展趋势…

悄悄话花费的时间(C语言)【二叉树各结点统计求和】

题目描述 给定一个二叉树&#xff0c;每个节点上站着一个人&#xff0c;节点数字表示父节点到该节点传递悄悄话需要花费的时间。 初始时&#xff0c;根节点所在位置的人有一个悄悄话想要传递给其他人&#xff0c;求二叉树所有节点上的人都接收到悄悄话花费的时间。 输入描述 …

LeetCode刷题----day6(1)

转载自该文章https://programmercarl.com/%E9%93%BE%E8%A1%A8%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html 链表基础 什么是链表 链表是一种通过指针串联在一起的线性结构&#xff0c;每一个节点由两部分组成&#xff0c;一个是数据域一个是指针域&#xff08;存放指向下一个…

挑战杯 基于卷积神经网络的乳腺癌分类 深度学习 医学图像

文章目录 1 前言2 前言3 数据集3.1 良性样本3.2 病变样本 4 开发环境5 代码实现5.1 实现流程5.2 部分代码实现5.2.1 导入库5.2.2 图像加载5.2.3 标记5.2.4 分组5.2.5 构建模型训练 6 分析指标6.1 精度&#xff0c;召回率和F1度量6.2 混淆矩阵 7 结果和结论8 最后 1 前言 &…

基于大数据的智能家居销量数据分析

文章目录 项目介绍主要功能截图&#xff1a;部分代码展示设计总结项目获取方式 &#x1f345; 作者主页&#xff1a;超级无敌暴龙战士塔塔开 &#x1f345; 简介&#xff1a;Java领域优质创作者&#x1f3c6;、 简历模板、学习资料、面试题库【关注我&#xff0c;都给你】 &…

vue : 无法加载文件 C:\Program Files\nodejs\node_global\vue.ps1,因为在此系统上禁止运行脚本。

解决方法&#xff1a; 打开PowerShell&#xff0c;在命令框输入set-ExecutionPolicy RemoteSigned 在PowerShell中输入会出现如下图&#xff0c;输入y即可。

数据结构链表力扣例题AC(3)——代码以及思路记录

160. 相交链表 给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&#xff0c;返回 null 。 AC写法一 struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {//思…

Nginx跳转模块之rewrite

一.location与rewrite模块的区别 rewrite&#xff1a;对访问的域名或者域名内的URL路径地址重写 location&#xff1a;对访问的路径做访问控制或者代理转发 二.rewrite模块基本内容 1.功能 通过正则表达式的匹配来改变URI&#xff0c;可以同时存在一个或多个指令&#xff0c…

echarts:显示图例(销量1、销量2)

1、代码 <!DOCTYPE html> <html> <head> <meta charset"UTF-8"> <title>Insert title here</title> </head> <body> <div id"main" style"width: 600px;height:400px;"></div> &l…

了解网络延迟-MDN文档学习笔记

了解延迟 查看更多学习笔记&#xff1a;GitHub&#xff1a;LoveEmiliaForever MDN中文官网 CDN CDN (内容分发网络) 指的是一组分布在各个地区的服务器 这些服务器存储着数据的副本&#xff0c;因此服务器可以根据哪些服务器与用户距离最近&#xff0c;来满足数据的请求 CD…

kubernetes的网络flannel与caclio

flannel网络 跨主机通信的一个解决方案是Flannel&#xff0c;由CoreOS推出&#xff0c;支持3种实现&#xff1a;UDP、VXLAN、host-gw udp模式&#xff1a;使用设备flannel.0进行封包解包&#xff0c;不是内核原生支持&#xff0c;上下文切换较大&#xff0c;性能非常差 vxlan模…

NestJS入门7:增加异常过滤器

前文参考&#xff1a; NestJS入门1 NestJS入门2&#xff1a;创建模块 NestJS入门3&#xff1a;不同请求方式前后端写法 NestJS入门4&#xff1a;MySQL typeorm 增删改查 NestJS入门5&#xff1a;加入Swagger NestJS入门6&#xff1a;日志中间件 本文代码基于上一篇文章《…

C语言实现直接插入排序

直接插入排序 其平均复杂度是 O(n2)&#xff0c;因此应用场景较少。 接插入排序的思路是&#xff1a; 每次处理一个数据&#xff0c;将其插入到一个已经排好序的子序列中&#xff0c;直到数据处理完毕。 下面给出一个动画示例&#xff1a; 这里写图片描述&#xff1a;从上面来…

Python 实现 ATR 指标计算(真实波幅):股票技术分析的利器系列(10)

Python 实现 ATR 指标计算&#xff08;真实波幅&#xff09;&#xff1a;股票技术分析的利器系列&#xff08;10&#xff09; 介绍算法解释 代码rolling函数介绍核心代码 完整代码 介绍 ATR&#xff08;真实波幅&#xff09;是一种技术指标&#xff0c;用于衡量市场波动性的程…

Windows+Yolo3-darknet训练自己数据集并测试

WindowsYolo3-darknet训练自己的数据集并测试 一、首要条件 Windows 7下配置好VS2015OPENCV3.4.2YOLO3CUDA10.0CUDNN7.5生成darknet.exe。具体配置可参考我的博客&#xff1a;https://blog.csdn.net/wszswllnzn_/article/details/100760477 二.制作数据集 1、方法1 使用软件la…