右值参数未按右值表现的C++代码编译问题排查
问题分析与解答
原代码报错原因
你的Holder构造函数签名确实是接收右值引用(Object&& _obj),但问题不在参数传递阶段,而是在构造函数内部的std::make_unique<Object>(_obj)调用中:
- 虽然
_obj是右值引用类型,但一旦它有了名字,在代码中就会被当作左值处理(这是C++的规则:有名字的右值引用是左值)。 - 当你直接把
_obj传给Object的构造函数时,编译器会尝试匹配拷贝构造函数,但你的Object类只定义了移动构造函数(Object(Object&&)),没有显式或隐式的拷贝构造函数(因为unique_ptr禁用了拷贝,所以Object的默认拷贝构造被删除了),因此触发编译错误。
修改后编译通过的原因
当你把代码改成std::make_unique<Object>(std::move(_obj))时:
std::move(_obj)的作用是把左值(有名字的右值引用)强制转换为右值类型。- 此时
Object的移动构造函数(Object(Object&&))会被匹配调用,而移动构造是合法的(unique_ptr支持移动),因此代码可以正常编译。
补充说明
你最初的误解是认为拷贝发生在参数传递阶段,但实际上参数传递时,Object(new int(42))是临时对象(右值),可以被Object&&正确绑定,没有拷贝。问题完全出在构造函数内部对_obj的使用方式上。
内容的提问来源于stack exchange,提问作者TheBeautifulOrc
相关产品推荐
相关产品推荐

