C++中未被调用的右值拷贝构造函数为何是编译必需的?
问题原因解析
1. 未添加移动构造时编译报错的根因
你最初定义的拷贝构造函数签名为shared_ptr(shared_ptr& src),仅支持接收非常量左值引用类型的入参,无法绑定到make_shared返回的临时右值对象。
C++的编译流程中,语法合法性校验优先级高于优化策略:即使编译器可以通过RVO(返回值优化)省略拷贝/移动构造的实际调用,也必须先通过重载决议确认存在合法可用的构造函数能完成该初始化操作,不会因为后续可以优化就跳过语法规则校验。因此在没有可用构造函数匹配右值入参时,编译器直接抛出绑定错误。
2. 添加移动构造后无打印输出的原因
该现象确实是RVO机制导致的:Visual Studio 2019的MSVC编译器在默认编译配置下(包括Debug、Release的默认参数)都会启用RVO优化,会直接将make_shared内部构造的shared_ptr对象直接构造在变量a的内存空间上,完全省略了移动构造函数的调用流程,因此你添加的打印语句不会执行。
如果需要验证移动构造的可调用性,可以临时关闭RVO优化:在MSVC的编译选项中添加/Od /Ob0禁用所有优化,重新编译运行就能看到移动构造的打印输出。
补充规则说明
C17标准引入了强制复制消除规则,对于shared_ptr<int> a = make_shared<int>(1)这类纯右值初始化场景,标准明确保证会省略拷贝/移动构造的调用,哪怕构造函数存在可观测的副作用也不会执行。但即使是C17标准下,也要求对应的构造函数未被显式删除,你最初的代码中仅有的拷贝构造无法适配右值入参,因此依然会编译失败。
内容的提问来源于stack exchange,提问作者Pan
相关产品推荐
相关产品推荐

