【问题标题】:Are move constructors required to be noexcept?移动构造函数是否必须是 noexcept ?
【发布时间】:2012-03-04 05:18:11
【问题描述】:

我一直在阅读一些关于是否允许抛出移动构造函数/赋值的相互矛盾的文章。

所以想问一下最终的C++11标准中是否允许move构造函数/赋值?

【问题讨论】:

  • 我在标准中没有看到任何关于不允许抛出移动构造函数的内容,但我确实看到“类 X 的隐式声明的移动构造函数将具有 X::X(X&&) 的形式”,我在里面看不到noexcept
  • 在最终草案中,我没有看到为任何函数声明的noexcept...
  • @ronag:你确定你在找吗?因为我打开 N3337 只搜索“noexcept”,立即得到了某个类的swap 函数。
  • @NicolBolas:我也这样做了,我发现的唯一地方是 declval,N3092。你从哪里得到 N3337?
  • @ronag:来自网站上今年的pre-Kona mailing。它基本上是 C++11 的免费副本,错别字已更正。此外,N3092 是古老的。那是从 2010 年开始的;我认为标准中还没有noexcept。或者如果他们这样做了,它仍然是新的,并且没有被外包给标准库。

标签: c++ c++11 noexcept


【解决方案1】:

通常允许抛出移动构造函数吗?是的。 应该他们吗?没有。

一般来说,您在其中所做的任何事情都不应该是可以抛出的任何东西。您不应该分配内存、调用其他代码或类似的事情。编写移动构造函数的唯一原因是潜逃他人的内存指针和对象引用。您应该复制一些基本类型并清空另一个对象中的值。那些东西不应该扔。

因此,虽然允许,但这不是一个好主意。如果您正在这样做,请重新考虑您在移动操作中所做的工作。

【讨论】:

  • 我假设移动构造函数中没有 stl 类型?我唯一应该担心的是美元?
  • @ronag:如果 std::type 在其移动构造函数中没有noexcept,则允许抛出。具体来说,基于节点的容器的一些实现有一个抛出移动构造函数,因为每个容器必须包含一个堆分配的端节点,甚至是空容器。这些相同容器的其他实现没有这种设计,因此可以(并且被允许)有一个 noexcept 移动构造函数。
【解决方案2】:

这里将进一步阐明这一点。

似乎std::vector 对是否使用noexcept 声明移动构造函数特别挑剔。如果你这样做了,那么 std::vector 将使用它们。如果您不这样做,则 std::vector 将改用您的复制构造函数。至少在某些情况下。尤其是在内部数组调整大小之后,它会在内部重新洗牌。

您可以在此示例中看到效果,其中没有声明 noexcept:

http://coliru.stacked-crooked.com/a/285cd07a9a52da3b

在这个例子中,它在哪里:

http://coliru.stacked-crooked.com/a/d043774ec4c279ec

在第一个示例中,std::vector 在第二次和第三次插入时已经使用了复制构造函数和 push_back。在第二个示例中,它执行相同的操作,但使用的是移动构造函数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-12-22
    • 2019-12-09
    • 2023-03-28
    • 2012-11-26
    • 2020-05-08
    • 2017-06-30
    • 2014-11-08
    相关资源
    最近更新 更多