为何类成员unique_ptr的移动构造函数未被调用?
含std::unique_ptr成员的类移动构造问题分析与解决
问题原因
编译错误的核心在于:右值引用参数本身是左值。
在你的移动构造函数C(C&& other): s(other.s) {}中,虽然other是C&&类型的右值引用,但other作为有名字的变量,它本身属于左值。直接访问other.s得到的是std::unique_ptr<S>&类型的左值,此时编译器会尝试调用std::unique_ptr已被删除的拷贝构造函数,而非预期的移动构造函数——这和你在code-1中必须用std::move(s1)将左值转为右值才能触发移动构造的逻辑完全一致。
修复方案
有两种简洁有效的修复方式:
方案1:用std::move转换成员为右值
在初始化std::unique_ptr成员时,通过std::move将other.s转为右值,触发std::unique_ptr的移动构造:
#include <memory> struct S {}; class C { private: std::unique_ptr<S> s = nullptr; public: C(C&& other): s(std::move(other.s)) {} // 添加std::move转换右值 C() = default; }; int main() { C c1; C c2(std::move(c1)); }
方案2:让编译器自动生成移动构造函数
当类包含不可拷贝但可移动的成员(如std::unique_ptr)时,编译器会自动生成正确的默认移动构造函数,只要你没有手动定义拷贝构造/拷贝赋值操作。直接默认移动构造函数即可,无需手动实现:
#include <memory> struct S {}; class C { private: std::unique_ptr<S> s = nullptr; public: C() = default; C(C&&) = default; // 让编译器自动生成移动构造 }; int main() { C c1; C c2(std::move(c1)); }
编译器生成的默认移动构造会对每个成员执行移动操作,完全符合需求。
内容的提问来源于stack exchange,提问作者Setu
相关产品推荐
相关产品推荐

