You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确将已定义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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 20:14:56