C++值传递与函数返回对象时拷贝构造函数未触发问题咨询
你遇到的两个现象都属于C++的**复制消除(Copy Elision)**规则的适用场景,具体对应规则如下:
1. func_1调用时无额外拷贝构造的原因
func_1(A(5))场景:A(5)是纯右值临时对象,当用纯右值初始化按值传递的形参时,C允许(C17及之后标准强制要求)直接在形参的内存空间上构造该临时对象,完全跳过拷贝/移动构造步骤。相当于你直接在func_1的形参obj的位置执行了A(5)构造,自然不会有额外的拷贝构造日志输出。func_1(5)场景:5是int类型,需要隐式调用A(int)构造函数转换为A类型,这个转换过程直接在形参obj的内存空间上完成,不需要先构造临时对象再拷贝到形参,所以同样不会触发额外的拷贝构造。
2. obj_7构造时仅一次拷贝构造的原因
你预期的两次拷贝分别是:①func_7返回时把入参obj拷贝构造为返回临时对象;②用返回临时对象拷贝构造obj_7。
实际运行时,编译器会把返回值的内存空间直接分配在obj_7的地址上,func_7内部return时的拷贝构造操作,直接把入参obj的内容拷贝到obj_7的内存空间,相当于两次拷贝合并为一次执行,因此只会输出一次拷贝构造日志。
注意:复制消除是C标准明确允许的优化行为,哪怕拷贝/移动构造函数存在可见副作用(比如你代码里的日志打印),优化仍然可以生效。C17及之后标准中,纯右值初始化同类型对象的场景下复制消除是强制要求的,和编译器优化等级无关;C++11/14标准下该优化为可选,但主流编译器默认都会开启,哪怕关闭优化等级也会生效。
内容的提问来源于stack exchange,提问作者Sarang Chaudhari
相关产品推荐
相关产品推荐

