如何正确将已定义std::unique_ptr的所有权转移至类对象成员?
关于
std::unique_ptr两次所有权转移的正确性与优化方案 你的实现是正确的
你当前的两次std::move操作完全合法,不会引发内存问题:
- 第一次
std::move(d1):将main中d1的所有权转移给构造函数的参数d(std::unique_ptr不可拷贝,必须通过move传递值类型参数); - 第二次
std::move(d):将构造函数参数d的所有权转移给成员变量m_class。
整个过程中,所有权始终唯一流转,每次move后原指针都会变为空,不存在双重释放或重复所有权的问题。
更优的实现方式
可以通过以下两种方式简化代码并减少不必要的move操作:
1. 右值引用参数+成员初始化列表
将构造函数改为接受std::unique_ptr<base>&&右值引用,并用初始化列表直接初始化成员变量,这样可以避免参数的移动构造,仅需一次move完成所有权转移:
class user { public: user(std::unique_ptr<base>&& d) : m_class(std::move(d)) {} void setVal(int val) { m_class->setVal(val); } int getVal() { return m_class->getVal(); } private: std::unique_ptr<base> m_class; };
main中的调用无需修改,std::unique_ptr<derived1>/std::unique_ptr<derived2>可以隐式转换为std::unique_ptr<base>&&,完美适配。
2. 模板构造函数(类型安全版)
如果需要更严格的类型校验,确保仅接受base的派生类unique_ptr,可以使用模板构造函数配合SFINAE:
#include <type_traits> class user { public: template<typename Derived, typename = std::enable_if_t<std::is_base_of_v<base, Derived>>> user(std::unique_ptr<Derived>&& d) : m_class(std::move(d)) {} void setVal(int val) { m_class->setVal(val); } int getVal() { return m_class->getVal(); } private: std::unique_ptr<base> m_class; };
这种方式既保留了对所有派生类的支持,又避免了非法类型的传入,同时消除了原代码中重复的重载构造函数。
内容的提问来源于stack exchange,提问作者Nick X Tsui
相关产品推荐
相关产品推荐

