C++中Person p2=Person(10)未调用拷贝构造函数是编译器优化吗
结论
你的代码没有编写错误,该现象是C++标准允许的编译器优化行为。
具体原理
- 你预设的「先创建临时
Person对象、再调用拷贝构造将临时对象赋值给p2」是未开启优化时的语义逻辑,但C++标准允许编译器在特定场景下跳过不必要的拷贝/移动构造操作,直接在目标对象的内存地址上完成构造,这个特性叫做拷贝消除(Copy Elision)。 - 你编写的
Person p2 = Person(10);属于拷贝消除的典型适用场景:用同类型纯右值(此处的临时Person对象属于纯右值)初始化对象时,编译器可以直接省略临时对象的创建和后续拷贝构造步骤,直接在p2对应的内存空间调用带int参数的构造函数,因此你看不到拷贝构造的输出。
验证方法
如果你使用GCC/Clang编译器,可以在编译时添加选项-fno-elide-constructors关闭拷贝消除优化,此时再运行程序就会输出你预期的日志:
paramererized constructor! Copy Constructor! Destructor! Destructor!
和你最初推测的执行逻辑完全一致。
补充说明
- C++11及更早版本中,拷贝消除属于编译器可选优化,绝大多数主流编译器默认都会开启该优化。
- 从C++17开始,这类同类型纯右值初始化场景的拷贝消除被标准强制要求实现,即使关闭上述编译选项,编译器也必须执行该优化,拷贝构造函数哪怕存在副作用也会被跳过,属于标准规定的合法行为。
内容的提问来源于stack exchange,提问作者timeil0611
相关产品推荐
相关产品推荐

