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

如何安全提取非空bar类的std::unique_ptr成员,避免对象意外失效?

安全实现bar到baz的数据转移,避免bar无效化

核心思路

利用C++的右值引用成员函数限定特性,只允许对右值状态的bar对象执行数据提取操作。右值bar代表对象即将被销毁(或用户明确要转移其资源),此时提取数据不会导致有效状态的bar变成空指针,从编译层面直接阻止误用。

具体实现

1. 修改bar类,添加右值限定的提取函数

struct foo {};

class bar
{
public:
    bar(std::unique_ptr<foo> data) : data{ std::move(data) }
    {
        if (!this->data)
        {
            throw std::invalid_argument{ "Unexpected null pointer" };
        }
    }

    foo* get_data() { return data.get(); }

    // 仅右值bar可调用的提取函数
    std::unique_ptr<foo> extract_data() && {
        return std::move(data);
    }

private:
    std::unique_ptr<foo> data;
};

2. 实现merge_data函数(两种可选方式)

方式一:全局merge_data函数

class baz
{
public:
    baz() = default;
    void add_data(std::unique_ptr<foo> data) { vec.push_back(std::move(data)); }
private:
    std::vector<std::unique_ptr<foo>> vec;
};

void merge_data(baz& target, bar&& source) {
    // 仅能对右值source调用extract_data
    target.add_data(std::move(source).extract_data());
}

方式二:将merge_data作为baz的成员函数

class baz
{
public:
    baz() = default;
    void add_data(std::unique_ptr<foo> data) { vec.push_back(std::move(data)); }

    void merge_data(bar&& source) {
        add_data(std::move(source).extract_data());
    }
private:
    std::vector<std::unique_ptr<foo>> vec;
};

安全机制说明

  • 编译层面阻止误用:如果尝试对左值bar(正常使用中的对象)调用extract_data(),编译器直接报错:
    bar valid_bar{std::make_unique<foo>()};
    valid_bar.extract_data(); // 编译失败!左值无法调用右值限定的成员函数
    
  • 语义明确:只有当bar是右值(临时对象或被std::move显式标记为可转移的对象)时,才能提取其数据,此时用户清楚知晓资源会被转移,不会误以为是拷贝操作。
  • 维护类约束:bar的data永远不会在有效生命周期内变为空指针,严格遵守了"bar必须始终处于有效状态"的设计要求。

使用示例

int main() {
    baz my_baz;

    // 临时bar对象(右值)直接合并
    my_baz.merge_data(bar{std::make_unique<foo>()});

    // 显式转移左值bar的所有权(用户明确知晓)
    bar temp_bar{std::make_unique<foo>()};
    my_baz.merge_data(std::move(temp_bar));
    // 此时temp_bar资源已被转移,语义上不再有效,不应继续使用
}

内容的提问来源于stack exchange,提问作者Involute

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 00:27:04