如何从存储基类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
相关产品推荐
相关产品推荐

