力学笃行系列之C++中的RVO优化,针对返回值为对象时临时对象的优化

2024-04-13 02:32

本文主要是介绍力学笃行系列之C++中的RVO优化,针对返回值为对象时临时对象的优化,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

摘要:
RVO (return value optimization) 和NRVO (named return value optimization) 是C++在处理一个函数返回类对象并将返回值赋给另一个对象时,为了减少拷贝构造次数以及析构次数而采用的一种编译器优化技术。
当函数的返回值为对象时,内部的调用是如何的,下面看例子:

#include <iostream>
using namespace std;
class Byte
{private: int  b;public:Byte(int bb=0):b(bb){cout<<"constructor,address:"<<this<<endl;}Byte(const Byte& byte){b=byte.b;cout<<"copy constructor,address:"<<this<<endl;}const Byte operator++(int){   Byte before(b);b++;return before;}int  getcr(){return b;}~Byte(){cout<<"deconstructor,address:"<<this<<endl;}
};int main()
{Byte tmp(10);const Byte tmp2=tmp++;                   //用一个对象来接受这个临时对象//const Byte* tmp2=&(tmp++);cout<<tmp2.getcr()<<endl;cout<<"compiler end"<<endl;
}

执行结果(g++加参数-fno-elide-constructors,去掉rvo优化):

constructor,address:0x7ffdb92f9a10               //tmp(10)    函数构造
constructor,address:0x7ffdb92f99e0               //构造before(b)
copy constructor,address:0x7ffdb92f9a30          //拷贝构造到临时对象
deconstructor,address:0x7ffdb92f99e0             //before调用析构函数
copy constructor,address:0x7ffdb92f9a20          //拷贝构造函数,从临时对象拷贝到tmp2
deconstructor,address:0x7ffdb92f9a30             //临时对象调用析构函数
10                                               //tmp.b的值为10
compiler end                                 
deconstructor,address:0x7ffdb92f9a20             //程序结束,释放tmp2
deconstructor,address:0x7ffdb92f9a10             //程序结束,释放tmp

去掉-fno-elide-constructors,rvo优化,结果:

constructor,address:0x7ffca1a17170                //tmp构造函数
constructor,address:0x7ffca1a17180                //tmp2构造函数
10
compiler end
deconstructor,address:0x7ffca1a17180              //tmp析构函数
deconstructor,address:0x7ffca1a17170              //tmp2析构函数

接下来,将函数改为:

int main()
{Byte tmp(10);//const Byte tmp2=tmp++;                  const Byte* tmp2=&(tmp++);                               //用指针指向临时对象的地址cout<<tmp2.getcr()<<endl;cout<<"compiler end"<<endl;
}

程序运行结果:

constructor,address:0x7ffc4f9a3420                //tmp(10)    函数构造
constructor,address:0x7ffc4f9a33f0                //构造before(b)
copy constructor,address:0x7ffc4f9a3430           //拷贝构造到临时对象
deconstructor,address:0x7ffc4f9a33f0              //before调用析构函数
deconstructor,address:0x7ffc4f9a3430              //临时对象调用析构函数
10                                                //临时对象地址已经被释放(此处为何仍能输出10,此处留下一个疑问)
compiler end
deconstructor,address:0x7ffc4f9a3420              //程序结束,释放tmp

去掉-fno-elide-constructors,rvo优化,结果:

constructor,address:0x7ffedc840340                   //tmp构造函数
constructor,address:0x7ffedc840350                   //临时对象构造函数
deconstructor,address:0x7ffedc840350                 //临时对象析构函数(为什么临时对象都释放掉了,还能调用函数得到b的值?)
10
compiler end
deconstructor,address:0x7ffedc840340                 //tmp析构函数

此时,我本文的目的就达到了,就是返回的对象是一个临时对象,这个函数执行完之后,就会释放,其他还有各种函数返回值优化的验证模型,比如将return Byte(b++)会是什么结果?编译器是如何对这些语句进行优化的?NRVO是如何优化的?这些都可以在《在深度探索C++对象模型》中得到答案,我本文的目的已经达到,就不在深究了,大家如果感兴趣的话可以在深入研究下。

这篇关于力学笃行系列之C++中的RVO优化,针对返回值为对象时临时对象的优化的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/898905

相关文章

Vue3 的 shallowRef 和 shallowReactive:优化性能

大家对 Vue3 的 ref 和 reactive 都很熟悉,那么对 shallowRef 和 shallowReactive 是否了解呢? 在编程和数据结构中,“shallow”(浅层)通常指对数据结构的最外层进行操作,而不递归地处理其内部或嵌套的数据。这种处理方式关注的是数据结构的第一层属性或元素,而忽略更深层次的嵌套内容。 1. 浅层与深层的对比 1.1 浅层(Shallow) 定义

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

HDFS—存储优化(纠删码)

纠删码原理 HDFS 默认情况下,一个文件有3个副本,这样提高了数据的可靠性,但也带来了2倍的冗余开销。 Hadoop3.x 引入了纠删码,采用计算的方式,可以节省约50%左右的存储空间。 此种方式节约了空间,但是会增加 cpu 的计算。 纠删码策略是给具体一个路径设置。所有往此路径下存储的文件,都会执行此策略。 默认只开启对 RS-6-3-1024k

【C++ Primer Plus习题】13.4

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "port.h"int main() {Port p1;Port p2("Abc", "Bcc", 30);std::cout <<

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

C++包装器

包装器 在 C++ 中,“包装器”通常指的是一种设计模式或编程技巧,用于封装其他代码或对象,使其更易于使用、管理或扩展。包装器的概念在编程中非常普遍,可以用于函数、类、库等多个方面。下面是几个常见的 “包装器” 类型: 1. 函数包装器 函数包装器用于封装一个或多个函数,使其接口更统一或更便于调用。例如,std::function 是一个通用的函数包装器,它可以存储任意可调用对象(函数、函数

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

06 C++Lambda表达式

lambda表达式的定义 没有显式模版形参的lambda表达式 [捕获] 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 有显式模版形参的lambda表达式 [捕获] <模版形参> 模版约束 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 含义 捕获:包含零个或者多个捕获符的逗号分隔列表 模板形参:用于泛型lambda提供个模板形参的名

MySQL高性能优化规范

前言:      笔者最近上班途中突然想丰富下自己的数据库优化技能。于是在查阅了多篇文章后,总结出了这篇! 数据库命令规范 所有数据库对象名称必须使用小写字母并用下划线分割 所有数据库对象名称禁止使用mysql保留关键字(如果表名中包含关键字查询时,需要将其用单引号括起来) 数据库对象的命名要能做到见名识意,并且最后不要超过32个字符 临时库表必须以tmp_为前缀并以日期为后缀,备份