力学笃行系列之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

相关文章

C++右移运算符的一个小坑及解决

《C++右移运算符的一个小坑及解决》文章指出右移运算符处理负数时左侧补1导致死循环,与除法行为不同,强调需注意补码机制以正确统计二进制1的个数... 目录我遇到了这么一个www.chinasem.cn函数由此可以看到也很好理解总结我遇到了这么一个函数template<typename T>unsigned

C++统计函数执行时间的最佳实践

《C++统计函数执行时间的最佳实践》在软件开发过程中,性能分析是优化程序的重要环节,了解函数的执行时间分布对于识别性能瓶颈至关重要,本文将分享一个C++函数执行时间统计工具,希望对大家有所帮助... 目录前言工具特性核心设计1. 数据结构设计2. 单例模式管理器3. RAII自动计时使用方法基本用法高级用法

从原理到实战解析Java Stream 的并行流性能优化

《从原理到实战解析JavaStream的并行流性能优化》本文给大家介绍JavaStream的并行流性能优化:从原理到实战的全攻略,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的... 目录一、并行流的核心原理与适用场景二、性能优化的核心策略1. 合理设置并行度:打破默认阈值2. 避免装箱

GO语言中函数命名返回值的使用

《GO语言中函数命名返回值的使用》在Go语言中,函数可以为其返回值指定名称,这被称为命名返回值或命名返回参数,这种特性可以使代码更清晰,特别是在返回多个值时,感兴趣的可以了解一下... 目录基本语法函数命名返回特点代码示例命名特点基本语法func functionName(parameters) (nam

Python实战之SEO优化自动化工具开发指南

《Python实战之SEO优化自动化工具开发指南》在数字化营销时代,搜索引擎优化(SEO)已成为网站获取流量的重要手段,本文将带您使用Python开发一套完整的SEO自动化工具,需要的可以了解下... 目录前言项目概述技术栈选择核心模块实现1. 关键词研究模块2. 网站技术seo检测模块3. 内容优化分析模

深入解析C++ 中std::map内存管理

《深入解析C++中std::map内存管理》文章详解C++std::map内存管理,指出clear()仅删除元素可能不释放底层内存,建议用swap()与空map交换以彻底释放,针对指针类型需手动de... 目录1️、基本清空std::map2️、使用 swap 彻底释放内存3️、map 中存储指针类型的对象

Java实现复杂查询优化的7个技巧小结

《Java实现复杂查询优化的7个技巧小结》在Java项目中,复杂查询是开发者面临的“硬骨头”,本文将通过7个实战技巧,结合代码示例和性能对比,手把手教你如何让复杂查询变得优雅,大家可以根据需求进行选择... 目录一、复杂查询的痛点:为何你的代码“又臭又长”1.1冗余变量与中间状态1.2重复查询与性能陷阱1.

Python内存优化的实战技巧分享

《Python内存优化的实战技巧分享》Python作为一门解释型语言,虽然在开发效率上有着显著优势,但在执行效率方面往往被诟病,然而,通过合理的内存优化策略,我们可以让Python程序的运行速度提升3... 目录前言python内存管理机制引用计数机制垃圾回收机制内存泄漏的常见原因1. 循环引用2. 全局变

使用Java读取本地文件并转换为MultipartFile对象的方法

《使用Java读取本地文件并转换为MultipartFile对象的方法》在许多JavaWeb应用中,我们经常会遇到将本地文件上传至服务器或其他系统的需求,在这种场景下,MultipartFile对象非... 目录1. 基本需求2. 自定义 MultipartFile 类3. 实现代码4. 代码解析5. 自定

C++ STL-string类底层实现过程

《C++STL-string类底层实现过程》本文实现了一个简易的string类,涵盖动态数组存储、深拷贝机制、迭代器支持、容量调整、字符串修改、运算符重载等功能,模拟标准string核心特性,重点强... 目录实现框架一、默认成员函数1.默认构造函数2.构造函数3.拷贝构造函数(重点)4.赋值运算符重载函数