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

如何从存储基类unique_ptr的vector中返回unique_ptr以实现polymorphism?

解决unique_ptr从vector返回时的拷贝错误问题

错误原因

std::unique_ptr是独占所有权的智能指针,它的拷贝构造函数被显式删除,确保同一时间只有一个unique_ptr持有对象的所有权。你的he函数试图直接返回t[x],本质是尝试拷贝vector中的unique_ptr,因此触发编译错误。

解决方案

根据实际需求,有三种常见解决方式:

1. 转移所有权(将元素从vector中移出)

如果需要把vector中元素的所有权转移出去(之后vector对应位置会变为空指针),修改函数参数为非const引用,并用std::move完成所有权转移:

unique_ptr<shape> he(vector<unique_ptr<shape>> &t, int x) {
    return std::move(t[x]);
}
  • 执行后,t[x]会被置为空,原对象的所有权完全转移给返回的unique_ptr。

2. 返回访问权限(不转移所有权)

如果仅需访问vector中的对象、不需要转移所有权,可返回原始指针或对象引用:

返回原始指针

shape* he(const vector<unique_ptr<shape>> &t, int x) {
    return t[x].get();
}
  • 调用方不能手动delete该指针,所有权仍归vector中的unique_ptr所有。

返回对象引用

shape& he(const vector<unique_ptr<shape>> &t, int x) {
    return *t[x];
}
  • 可直接通过引用来操作对象,所有权保留在vector中。

3. 返回对象副本(多态克隆)

如果需要返回独立的对象副本,需给基类添加克隆函数实现多态拷贝:
首先修改基类,添加虚析构和克隆函数:

class shape {
public:
    virtual void foo() = 0;
    virtual unique_ptr<shape> clone() const = 0;
    virtual ~shape() = default; // 必须添加虚析构,避免内存泄漏
};

然后在派生类中实现克隆:

class circle : public shape {
public:
    virtual void foo() override {cout << "I am circle" << endl;}
    unique_ptr<shape> clone() const override {
        return make_unique<circle>(*this);
    }
};

class square : public shape {
public:
    virtual void foo() override {cout << "I am square" << endl;}
    unique_ptr<shape> clone() const override {
        return make_unique<square>(*this);
    }
};

最后修改he函数:

unique_ptr<shape> he(const vector<unique_ptr<shape>> &t, int x) {
    return t[x]->clone();
}
  • 返回的是全新的unique_ptr,指向原对象的副本,vector中的原对象不受影响。

额外注意

原始代码中基类shape缺少虚析构函数,会导致用unique_ptr<shape>管理派生类对象时,销毁阶段无法正确调用派生类析构函数,引发内存泄漏。务必添加virtual ~shape() = default;。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 19:05:26