C++17中依赖函数参数的返回值可被优化吗?代码输出问询
问题:返回值依赖函数参数时,能否省略构造优化?
当返回值依赖函数参数时,返回值能否被优化掉?
对于以下代码,在C++17环境下得到的输出为:
move ctor dtor -------------------------------------------------------------------------------- dtor
是否也可能得到如下输出(省略move构造,直接在调用方构造对象)?请回答是或否并说明原因:
-------------------------------------------------------------------------------- dtor
对应的代码:
struct Foo { Foo() {} Foo(const Foo&) { std::cout << "copy ctor" << std::endl; } Foo(Foo&&) { std::cout << "move ctor" << std::endl; } ~Foo() { std::cout << "dtor" << std::endl; } }; Foo passit(Foo f) { return f; } int main() { Foo f = passit(Foo{}); std::cout << std::string(80, '-') << std::endl; }
回答:是
原因如下:
- 这牵扯到命名返回值优化(NRVO)和C++17的强制复制消除规则。对于
return f;这种返回函数参数的场景,虽然C++17没有强制要求必须消除移动/复制构造,但编译器完全可以选择进行优化。 - 当编译器开启优化(比如GCC、Clang添加
-O2参数)时,能完成两步关键优化:passit(Foo{})中的临时对象Foo{}会被直接构造到passit的参数f的内存位置上——这是C++17强制要求的临时对象消除,不需要额外构造临时对象再做移动/复制操作。- 执行
return f;时,编译器会直接将f的内存位置与main函数中Foo f的内存位置绑定,省略掉返回时的移动构造步骤。
- 当这两步优化全部生效后,整个程序只会构造一次
Foo对象,最终就会出现你提到的仅输出分隔线和一次析构函数调用的结果。
内容的提问来源于stack exchange,提问作者dwto
相关产品推荐
相关产品推荐

