C++如何按值向函数传递临时对象?xvalue传值无拷贝构造调用原理
原理详解
你观察到的现象是C++移动语义重载规则 + 复制消除优化共同作用的结果,核心流程和原理如下:
1. 按值传参的构造函数匹配规则
按值传递参数并不代表一定会触发拷贝构造:C++的重载决议会根据实参的值类别选择最优的构造函数完成形参初始化:
- 当实参是左值时,匹配拷贝构造函数
Object(const Object&),这就是你第一个示例中第一次输出拷贝构造日志的原因 - 当实参是右值(包括纯右值临时对象、xvalue到期值)时,优先匹配移动构造函数
Object(Object&&),不会调用拷贝构造,这就是你第二个示例中没有出现拷贝构造日志的根本原因
2. 第二个示例的完整执行流程
你给出的第二个示例代码的实际执行流程,在默认开启编译器优化的情况下如下:
- 执行
Object(5),直接调用普通构造函数,输出Object::ctor,生成一个纯右值临时对象 - 用这个纯右值初始化
take_and_return_obj的按值形参o:匹配移动构造函数,输出Object::move-ctor(也就是你看到的那一次移动日志) - 函数返回形参
o时,编译器触发命名返回值优化(NRVO):直接将形参o构造到main函数中接收返回值的变量o的内存地址上,跳过了返回值构造、目标变量初始化这两步本该执行的移动构造,所以没有额外的移动/拷贝日志输出
3. 验证方式
如果关闭编译器的复制消除优化,可以看到完整的未优化流程:
给GCC/Clang添加编译参数-fno-elide-constructors后运行第二个示例,输出会变为:
Object::ctor Object::move-ctor // 形参初始化 Object::move-ctor // 函数返回值构造 Object::move-ctor // main函数变量o初始化
这也验证了按值传右值时,形参会用移动构造完成初始化的规则。
内容的提问来源于stack exchange,提问作者Rares Dima
相关产品推荐
相关产品推荐

