为什么我不能使用{std::move(first), std::move(second)}实例化std::vector<std::unique_ptr<int>>?

10

我有一个简单的函数,它应该构造一些对象并返回它们的向量同时转移所有权。我认为最好的方法是返回对象的 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;
}
为什么第二种解决方案可行而第一种不可行?有没有解决方法可以让我在使用初始化列表的短而简单语法的情况下使用?

4
据我所知,由于初始化列表被传递后,您会将其元素复制到向量中,而不是将它们移动。 - Matthieu Brucher
建议您在示例中不要使用int(因为很少有指向单个int值的指针是有意义的),而是建议您创建一个简单的类或结构来使用。它不必完全定义,因为这与问题无关,但至少会更有意义。例如,可以使用虚拟的Foo替代int - Some programmer dude
2个回答

3
第二种解决方案为什么可行而第一种不可行?
你使用的列表初始化语法调用了接受std :: initializer_list的构造函数。然而,std :: initializer_list不可移动,而std :: initializer_list >不可复制,因此无法调用构造函数。
在后一个示例中,您使用默认构造函数,因此没有问题。
有没有解决方法可以让我在使用初始化程序列表的简短和简单语法时使用?
您可以列出初始化数组,并使用一对移动迭代器:
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可移动,但它没有被采纳(尚未被采纳;谁知道未来会带来什么)。


谢谢,我接受了你的答案。这个问题刚被标记为重复,并且链接的帖子提供了相同的解决方法。感谢提供提案的链接! - TomsonTom

1
在我的平台上,相关代码如下:

On my platform, the relevant code is:

  vector(initializer_list<value_type> __l,
   const allocator_type& __a = allocator_type())
  : _Base(__a)
  {   _M_range_initialize(__l.begin(), __l.end(),
          random_access_iterator_tag());
  }

_M_range_initialize() 只是从迭代器中 复制,而不是移动。


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