将派生类 unique_ptr 添加到基类 unique_ptr 的向量中

7

我有一个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

3个回答

9

5

这是因为你无法复制一个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));    
               // ^^^^^^^^^^             ^
}

这里有一个实时演示


如果这个解决方案似乎不起作用,请确保类的继承是公共的。 - josh-stackoverflow

3

关于unique_ptr的cppreference

如果T是某个基类B的派生类,则std::unique_ptr < T >可以隐式转换为std::unique_ptr < B >。

因此,问题不在于转换失败。

该类满足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拥有的对象将被处理掉。演示。

如果您想同时创建对象并将其推送到向量中,我建议使用emplace_back函数: vec.emplace_back(new Derived()); - Marcin Kolny
@Marcin,去掉new,你就对了。 - rubenvb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接