编译器对临时变量的优化--简单理解
2010-08-21 00:07
375 查看
编译器对临时变量的优化--简单理解
2010-7-6
烛秋
2010-8-20整理
一、问题来源
之前对NRV优化做了一点总结,还有所欠缺,只分析了 A b = f();的情况,没有去分析A b; b = f();的情况。又想起之前看过的书,对产生临时对象的讲解都是假设了编译器没有进行优化,然后说要提高C++程序性能,必须尽量的少使用返回对象,因为那样才不会产生临时对象。多使用引用/指针可以减少临时对象的产生,提高程序性能,这个观点没有错。但事实上很多编译器多做了优化,使得临时对象的产生减少了很多,打算以最简单的例子对编译器的优化做简单的理解。
代码:
二、分析
对于采用了NRV优化的编译器来说(例如:VS的release模式、G++),没有临时对象产生。但是对于debug模式下,会产生临时对象。
Debug模式下做法是:局部对象-->临时对象-->外部对象。
说明:第一个箭头调用拷贝构造函数产生了临时对象,第二个箭头调用operator=操作。
Release模式下做法是:局部对象-->外部对象。
说明:调用operator=操作
从图1和图3可以看到,调用operator=操作都是在main()函数中进行,这就意味着operator=的右值必须是存在的对象。在debug模式下,临时对象的地址是在main()函数作用域中,这没有问题。在release模式下,“临时对象"和局部对象合并了。原因如下:局部对象是在函数f()中创建的,但是它的地址空间是main()函数的,从图3和图4可以看到创建局部对象时,使用的地址空间是在main()中申请的“临时对象”空间。这点跟上一篇文章分析的NRV优化类似,都是把临时对象的地址传递进函数f(),然后局部对象就在这个地址上创建,这样就减少了拷贝构造函数的调用。
三、OD调试截图
图 1 debug模式main()函数
图 2 debug模式f()函数
图 3 release模式main()函数
图 4 release模式f()函数
2010-7-6
烛秋
2010-8-20整理
一、问题来源
之前对NRV优化做了一点总结,还有所欠缺,只分析了 A b = f();的情况,没有去分析A b; b = f();的情况。又想起之前看过的书,对产生临时对象的讲解都是假设了编译器没有进行优化,然后说要提高C++程序性能,必须尽量的少使用返回对象,因为那样才不会产生临时对象。多使用引用/指针可以减少临时对象的产生,提高程序性能,这个观点没有错。但事实上很多编译器多做了优化,使得临时对象的产生减少了很多,打算以最简单的例子对编译器的优化做简单的理解。
代码:
/* */ ///////////////////////////////////////////////// /* *命令行编译: *g++ -o 1.exe 1.cpp */ ///////////////////////////////////////////////// ///////////////////////////////////////////////// #include <iostream> #include <cstring> using namespace std; class A { public: A() { cout<<"construct"<<endl; strcpy(name,"zhangsan"); } ~A() { cout<<"destruct"<<endl; } A(const A& temp) { cout<<"copy"<<endl; strcpy(name,temp.name); } A& operator= (const A& temp) { cout << "operator=" << endl; strcpy(name, temp.name); return *this; } private: char name[16]; }; //////////////////////////// A f() { cout<<"------------function f----------"<<endl; A b; return b; } //////////////////////////// int main() { A b; b = f();//A b(f()); return 0; } /* 测试输出结果: VS2005release模式//优化了 construct ------------function f---------- construct operator= destruct destruct */ /* vs2005Debug模式//未优化,跟书上的一致 construct ------------function f---------- construct copy destruct operator= destruct destruct */
二、分析
对于采用了NRV优化的编译器来说(例如:VS的release模式、G++),没有临时对象产生。但是对于debug模式下,会产生临时对象。
Debug模式下做法是:局部对象-->临时对象-->外部对象。
说明:第一个箭头调用拷贝构造函数产生了临时对象,第二个箭头调用operator=操作。
Release模式下做法是:局部对象-->外部对象。
说明:调用operator=操作
从图1和图3可以看到,调用operator=操作都是在main()函数中进行,这就意味着operator=的右值必须是存在的对象。在debug模式下,临时对象的地址是在main()函数作用域中,这没有问题。在release模式下,“临时对象"和局部对象合并了。原因如下:局部对象是在函数f()中创建的,但是它的地址空间是main()函数的,从图3和图4可以看到创建局部对象时,使用的地址空间是在main()中申请的“临时对象”空间。这点跟上一篇文章分析的NRV优化类似,都是把临时对象的地址传递进函数f(),然后局部对象就在这个地址上创建,这样就减少了拷贝构造函数的调用。
三、OD调试截图
图 1 debug模式main()函数
图 2 debug模式f()函数
图 3 release模式main()函数
图 4 release模式f()函数
相关文章推荐
- 图像处理的简单优化-03:优化-消除临时变量
- sql server 存储过程的优化.(变量表,临时表的简单分析)
- C++以对象作为返回值时编译器的优化,以及临时变量的析构时机
- sql server 存储过程的优化.(变量表,临时表的简单分析) (转)
- sql server 存储过程的优化.(变量表,临时表的简单分析)
- MYSQL的存储过程、变量、函数及部分简单优化(非常有用,有存储过程+光标实例)
- 用类名做方法的返回值类型 在学习Java的初始阶段,很多同学使用基本数据类型定义变量和引用类型定义变量以及使用类名做方法的返回值类型常常不知所以。今天我以自己的解读方式和个人的理解作一个简单的解释,和
- SSE2的简单理解,主要针对opencv 中的优化
- 用volatile关键字防止变量被编译器优化
- 深度学习(四十)优化求解系列(2)简单理解神经网络求解过程-未完待续
- 深入理解JVM读书笔记四: (早期)编译器优化
- 临时变量理解
- JavaScript中作用域和作用域链的简单理解(变量提升)
- centos学习:理解环境变量 临时、永久
- javascript编写一个简单的编译器(理解抽象语法树AST)
- php中静态全局变量和全局变量的简单理解
- python 全局变量的简单理解
- C++中有关volatile关键字的作用--阻止编译器将其变量优化缓存到寄存器(和线程相关)(转自百度)
- KEIL编译器【C语言编译选项优化等级说明】【支持C99(变量声明在执行语句之后)】【反汇编设置】【C语言联合汇编】
- 简单理解python下的变量和内存