首页 > 解决方案 > 为什么我不能实例化 std::vector> 使用 {std::move(first), std::move(second)}?

问题描述

我有一个简单的函数,它应该构造一些对象并返回它们的向量,同时还转移所有权。我认为最好的方法是简单地返回一个std::vector<std::unique_ptr<int>>对象(假设它们是int)。

当我尝试以下功能时:

std::vector<std::unique_ptr<int>> create_stuff() {
    auto first = std::make_unique<int>(1);
    auto second = std::make_unique<int>(2);
    return {std::move(first), std::move(second)};
}

我受到了一个非常长的编译错误的欢迎,其结尾是:

xmemory0(737): error C2280: 'std::unique_ptr<int,std::default_delete<_Ty>>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)':
attempting to reference a deleted function

我认为问题出在函数本身,但是以下解决方案运行良好:

std::vector<std::unique_ptr<int>> create_stuff() {
    auto first = std::make_unique<int>(1);
    auto second = std::make_unique<int>(2);
    std::vector<std::unique_ptr<int>> results;
    results.push_back(std::move(first));
    results.push_back(std::move(second));
    return results;
}

为什么第二个解决方案有效但第一个解决方案无效?是否有一种解决方法可以让我在初始化列表中使用简短而简单的语法?

标签: c++unique-ptrinitializer-list

解决方案


为什么第二个解决方案有效但第一个解决方案无效?

您使用的列表初始化语法调用接受std::initializer_list. std::initializer_list虽然不可移动,std::initializer_list<std::unique_ptr<T>>也不可复制,因此无法调用构造函数。

在后一个示例中,您使用默认构造函数,因此没有问题。

是否有一种解决方法可以让我在初始化列表中使用简短而简单的语法?

您可以列出初始化数组,并使用一对移动迭代器:

std::array arr{
    std::make_unique<int>(1),
    std::make_unique<int>(2),
};
return std::vector(
    std::make_move_iterator(std::begin(arr)),
    std::make_move_iterator(std::end(arr))
);

有一个提议std::initializer_list可移动,但它没有被采纳(还没有被采纳;谁知道未来会带来什么)。


推荐阅读