【问题标题】:std::list of move-only type: Cannot emplace into std::vector in VC++std::list of move-only type: 在 VC++ 中不能进入 std::vector
【发布时间】:2019-10-30 03:05:28
【问题描述】:

在 VC++ 2019 中,我不能 emplace_back 一个(右值)list 仅移动类型。

#include <vector>
#include <list>

struct A
{
    A(A&&) {}
};

using ListOfA = std::list<A>;

int main()
{
    std::vector<ListOfA> v;

    // Build error in VC++ 2019
    // No error in Clang and GCC C++11 - C++2a
    v.emplace_back(std::move(ListOfA()));
}

尝试在 VC++ 2019 中构建会出现以下编译错误:

'A::A(const A &amp;)': attempting to reference a deleted function

显然,VC++ 正在尝试实例化 A 的(左值)复制构造函数,但它(正确地)不存在,因为我已明确定义了 A 的构造函数之一。

我认为通过从另一个 list 移动来在 vector 中就地实例化 list 应该是有效的 - 也就是说,list 类确实有一个 move constructor 我' d 认为应该简单地使新的list 接管(移出)list 中的元素的所有权,而不需要任何副本。

其实使用Wandbox,same code builds and runs without error使用GCC和Clang。

有人可以解释为什么这段代码在 VC++ 2019 中无法编译吗?我是否有误解 - 实际上是否有正当理由说明(左值)复制构造函数在上面的代码中被 VC++ 编译器实例化?


注意

std::move(...) 不存在时,VC++ 中也会出现同样的错误;即这一行出现同样的错误:

v.emplace_back(ListOfA());

【问题讨论】:

  • Clang 打印出一条有趣的消息:warning: moving a temporary object prevents copy elision [-Wpessimizing-move]
  • 你不需要std::move 一个临时的。尝试摆脱std::move,看看VC会发生什么(gcc非常高兴)。
  • 您可以通过查看所有错误消息转储来推断这一点,并查看调用了哪个std::list 构造函数。或者,向您的类添加一个复制构造函数,在复制构造函数中设置一个断点,然后查看调用堆栈。
  • 事实上,std::is_nothrow_move_constructible_v&lt;ListOfA&gt; 在 gcc 9 中给出 1 在 MSVC 19 中给出 0
  • 当我实现复制构造函数并在那里和移动构造函数中放置断点时,只到达移动构造函数。未达到复制构造函数。尽管 std::is_nothrow_move_constructible_v&lt;ListOfA&gt; 返回 false,但不知何故 VC++ 正在调用 list 移动构造函数

标签: c++ list visual-c++ move-semantics


【解决方案1】:

MSVC 使用 std::list 的复制构造函数,因为它的移动构造函数正在抛出。在重新分配过程中,如果移动构造函数抛出,std::vector 无法提供标准要求的强异常保证。

在您的情况下,向量在重新分配之前没有任何元素,因此似乎没有调用复制构造函数,但这并不意味着不需要复制构造函数。

std::list 在 libstdc++ 和 libc++ 中具有 noexcept 移动构造函数。这是允许的,但标准没有要求。

【讨论】:

  • 谢谢!我想知道为什么lists 移动构造函数,而不是复制构造函数,在 VC++ 中抛出。
  • @DanNissenbaum 复制构造函数可能会抛出,但向量可以通过恢复到原始存储来恢复。 (对于移动,不能保证被移动的元素仍然可用。)
  • 一个细节:你写了during reallocation, ...。我认为 cmets 也适用于向量的分配(即向量的构造) - 对吗?
  • 实际上 - 我现在看到在 allocation 的情况下“没有什么可以恢复”。因此,似乎 cmets 仅适用于重新分配。
  • 哇,这个问题和答案真的让我想到了异常保证,noexcept 等等。 (以及它与const 的关系。)感谢您指路!
猜你喜欢
  • 2020-08-16
  • 2017-10-19
  • 2019-07-09
  • 2019-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多