将派生类的unique_ptr添加到基类unique_ptr的vector上

Add unique_ptr of derived class to vector of base class unique_ptr

本文关键字:unique ptr 基类 vector 添加 派生      更新时间:2023-10-16

我有一个std::unique_ptr<Derived>,我想添加到std::vector<std::unique_ptr<Base>>

std::unique_ptr<Derived> derivedObject;
std::vector<std::unique_ptr<Base>> vec;
vec.push_back(derivedObject) // Invalid arguments

unique_ptr保证它只有一个指向内存的指针,所以你不能只是把它复制到vector中,你需要移动它:

vec.push_back(std::move(derivedObject));

如果您查看unique_ptr构造函数(http://en.cppreference.com/w/cpp/memory/unique_ptr/unique_ptr),您会发现这个类没有实现复制构造函数,而是实现移动构造函数(http://en.cppreference.com/w/cpp/language/move_constructor)。

这是因为您无法复制std::unique_ptr。使用std::move():

可以解决这个问题。
#include <iostream>
#include <memory>
#include <vector>
struct Base {
};
struct Derived : public Base {
};
int main()
{
    std::unique_ptr<Derived> derivedObject;
    std::vector<std::unique_ptr<Base>> vec;
    vec.push_back(std::move(derivedObject));    
               // ^^^^^^^^^^             ^
}

cppreference about unique_ptr

如果T是某基B的派生类,则std::unique_ptr 隐式转换为std::unique_ptr .

所以,问题不在于转换失败。

类满足MoveConstructible和MoveAssignable的要求,但不满足CopyConstructible和CopyAssignable的要求。

这就是导致失败的原因。unique_ptr可以移动,但不能复制,因为这会破坏单一所有权协议。


所以要么使用std::move,要么直接使用make_derived

vec.push_back(std::move(derivedObject));  //Option 1. When unique_ptr is already created.
OR,
vec.push_back(make_unique<Derived>());    //Option 2. New unique_ptr

使用选项#2,您可以避免有一个没有目的的局部变量。无论如何,当在unique_ptr上执行move时,unique_ptr拥有的对象被释放了。演示。