C++编译器的RVO和NRVO
1、说明
我一直记得返回对象的函数在调用时会有拷贝构造动作,但是最近实际测试却和记忆有些偏差,经查询是编译的问题
RVO: return value optimization
NRVO: named return value optimization
这两个是编译器的一种函数返回值优化策略
先说结果,VS在debug模式下默认 RVO,release模式下默认 NRVO;而g++在debug和release下都默认NRVO
2、示例
先看一组代码
class Test
{
public:
explicit Test(int num)
: num(num)
{
cout << "constructor " << num << endl;
}
Test(const Test &test)
{
cout << "copy constructor " << test.num << endl;
num = test.num;
}
~Test()
{
cout << "destructor " << num << endl;
}
void print() const
{
cout << "print " << num << endl;
}
private:
int num{};
};
Test getTest(int num)
{
Test test(num);
return test;
}
int main()
{
Test test2 = getTest(12);
test2.print();
return 0;
}
函数 getTest() 返回一个对象,main() 函数中调用并复制给变量理应有一个拷贝构造的动作,但是实际上返回值为
constructor 12
print 12
destructor 12
打印变量地址也发现,getTest() 函数内的变量 test 和 main() 函数中的变量 test 的地址居然是一样的。是我记错了吗?其实不是,根据C++语法,确实应该有拷贝构造的动作,这里的结果是编译器优化的后的,就是上文所说的 RVO 和 NRVO
3、编译器优化
g++ 可以使用参数 -fno-elide-constructors 来关闭优化,CMakeList 使用以下代码关闭
add_compile_options(-fno-elide-constructors)
或者
set(CMAKE_CXX_FLAGS “-fno-elide-constructors ${CMAKE_CXX_FLAGS}”)
如果我们关闭编译器的优化,最后输出的结果应该是
constructor 12 //getTest()函数内构造test对象
copy constructor 12 //getTest()的返回值不能是test对象,需要一个临时变量,使用test对象拷贝构造临时对象_test
destructor 12 //getTest()返回,test对象被析构
copy constructor 12 //main()函数使用test2变量接收临时对象_test
destructor 12 //临时对象_test被析构
print 12 //print()调用
destructor 12 //main()函数内test2对象被析构
不难理解,我的记忆没错,根据C++语法确实应该有拷贝构造,只不过是编译器优化了
C++编译器的RVO和NRVO的更多相关文章
- C++编译器优化技术:RVO、NRVO和复制省略
现代编译器缺省会使用RVO(return value optimization,返回值优化).NRVO(named return value optimization.命名返回值优化)和复制省略(Co ...
- RVO和NRVO
返回值优化(Return Value Optimization,简称RVO),是这么一种优化机制:当函数需要返回一个对象的时候,如果自己创建一个临时对象用户返回,那么这个临时对象会消耗一个构造函数(C ...
- 第15课 右值引用(2)_std::move和移动语义
1. std::move (1)std::move的原型 template<typename T> typename remove_reference<T>::type& ...
- duang!!!为什么函数能够返回unique_ptr
C++虐我千百遍,我待C++如初恋 从智能指针说起 对高手而言.指针是上天入地的神器.对新手而言,那简直是灾难的源泉.高级语言如Java,C#都自己主动管理内存.你仅仅管new.不必担心内存释放问题. ...
- C++返回值优化
返回值优化(Return Value Optimization,简称RVO)是一种编译器优化机制:当函数需要返回一个对象的时候,如果自己创建一个临时对象用于返回,那么这个临时对象会消耗一个构造函数(C ...
- C++ 11 右值引用以及std::move
转载请注明出处:http://blog.csdn.net/luotuo44/article/details/46779063 新类型: int和int&是什么?都是类型.int是整数类型,in ...
- Effective Modern C++:05右值引用、移动语义和完美转发
移动语义使得编译器得以使用成本较低的移动操作,来代替成本较高的复制操作:完美转发使得人们可以撰写接收任意实参的函数模板,并将其转发到目标函数,目标函数会接收到与转发函数所接收到的完全相同的实参.右值引 ...
- copy elison & RVO & NRVO
蓝色的博文 To summarize, RVO is a compiler optimization technique, while std::move is just an rvalue cast ...
- 返回值优化(RVO)
C++的函数中,如果返回值是一个对象,那么理论上它不可避免的会调用对象的构造函数和析构函数,从而导致一定的效率损耗.如下函数所示: A test() { A a; return a; } 在test函 ...
- 【M20】协助完成“返回值优化(RVO)”
1.方法返回对象,会导致临时对象的产生,这降低了效率,const Rational operator* (const Rational& lhs,Rational& rhs).有没有什 ...
随机推荐
- 给科研人的 ML 开源发布工具包
什么是开源发布工具包? 恭喜你的论文成功发表,这是一个巨大的成就!你的研究成果将为学界做出贡献. 其实除了发表论文之外,你还可以通过发布研究的其他部分,如代码.数据集.模型等,来增加研究的可见度和采用 ...
- 前端知识点 | 查看已登录网站 Cookie 信息
方法一:针对 Chrome 浏览器 设置 \(\to\) 隐私设置和安全性 \(\to\) Cookie 及其他网站数据 \(\to\) 查看所有 Cookie 和网站数据 or chrome://s ...
- POJ 1236 Network of Schools (连通图 - Garbow 算法)
POJ 1236 Network of Schools 校园网:给定N所学校和网络,目标是分发软件其他学校都可收到,求①所需最少分发学校数:②若任选学校都能收到,最低新增边数. 思路:同一个强连通 ...
- Educational Codeforces Round 99 (Rated for Div. 2) (A ~ F)个人题解
Educational Codeforces Round 99 (Rated for Div. 2) A. Strange Functions 读懂题即可(或者快速看一下样例解释),直接输出字符串长度 ...
- 第五届蓝桥杯(2014)C/C++大学A组省赛题解
第一题.猜年龄 小明带两个妹妹参加元宵灯会.别人问她们多大了,她们调皮地说:"我们俩的年龄之积是年龄之和的6倍".小明又补充说:"她们可不是双胞胎,年龄差肯定也不超过8岁 ...
- Spring EL 表达式
本篇讲述了Spring Expression Language -- 即Spring3中功能丰富强大的表达式语言,简称SpEL. SpEL是类似于OGNL和JSF EL的表达式语言,能够在运行时构建复 ...
- vue-router路由复用后页面没有刷新
vue-router提供了页面路由功能,可以用来构建单页面应用,在使用vue-router的动态路由匹配的时候,遇到了url变化了,但是页面却没有任何动静的问题,记录一下. 动态路由匹配url变化了, ...
- Linux环境下如何查看Python版本号
方法一.直接执行命令python,就可以查看python的版本信息. 退出用exit() 方法二.利用命令python -V,注意V要大写. 方法三.利用命令whereis python,注意wher ...
- spring--集成RocketMQ
在Spring Boot中集成RocketMQ通常涉及以下步骤: 1. **添加依赖**:首先,需要在项目的`pom.xml`文件中添加RocketMQ的Spring Boot Starter依赖. ...
- 【MLA】内存泄漏检查
项目地址:skullboyer/MLA (github.com) 介绍 MLA 即 Memory Leak Analyzer,是一个排查内存泄漏的分析器 实现机制是在malloc时记录分配位置信息,在 ...