按值返回,noexcept

时间:2012-03-17 20:29:20

标签: c++ noexcept

我目前正在努力探索noexcept(几乎每个人都避免使用旧的“运行时异常规范”)。虽然我认为我得到了noexcept的基本概念,但我不确定在以下情况下会发生什么:

class sample {
public:
  sample() noexcept { }//this doesn't throw
  sample(const sample & s) noexcept { }
  sample(sample && s) noexcept { }
  sample & operator=(const sample & s) noexcept {...}
  sample & operator=(sample && s) noexcept { ... }
  ~sample() noexcept() { }//this should never ever throw
  sample operator-() const { return *this * -1; }//assuming that there is a operator*…
  sample & operator*=(const sample & s) noexcept { ... }
};

sample operator*(sample s1, const sample & s2) { return s1 *= s2; }//same problem as with operator-…

将示例:: operator-声明为noexcept是否安全? (考虑到它在返回时调用构造函数)

编辑:我更新了代码部分,因为问题的核心部分似乎并不清楚......

2 个答案:

答案 0 :(得分:2)

修改后:保证operator-的实施不会引发任何异常(至少如果您将operator*标记为noexcept,那么is),因此将其标记为noexcept是安全的。我真的不明白你的担忧,但我可能会错过这个问题的原因。所有操作(包括潜在的复制或移动构造)都明确标记为noexcept ...问题在哪里?


除非您明确将其标记为noexcept,否则它将不具备该资格。现在,根据operator* copy-constructor 的实现,它实际上可能永远不会抛出,但这不会使它成为noexcept

copy-constructor 开始,如果你没有定义它,隐式声明的复制构造函数将是noexcept或不是,具体取决于你的类型的所有成员是否{ {1}}(再次,不仅是他们不扔,而且他们有资格)

答案 1 :(得分:1)

你的问题是,“它安全吗?”。我宁愿问,“将某些函数声明为noexcept甚至只是因为它们不会抛出异常才有意义吗?”。

严格来说,noexcept提供了两件事:

  1. 任何人都可以在编译时检查你的函数是否被声明为noexcept。 (这实际上只在一个std函数中有用:move_if_noexcept)
  2. 你得到一个运行时保证,如果你的函数仍试图抛出异常,它就不会离开函数(因为调用了std :: terminate)。
  3. 更有趣的是,列出提供的noexcept:

    1. 如果函数确实没有抛出,则在编译时自动检查
    2. 更重要的是,它不提供任何“例外安全保证”。
    3. 我相信在学习noexcept时经常会忽略第二项。如果你想提供一个不失败的保证(请注意,这与无投掷保证不同,因为该函数可能会失败,但不会抛出),你可以在你的函数中简单地实现它并且不抛出任何东西,并将它记录在某个地方。您不需要将函数标记为noexcept。无论如何,它将提供无故障异常安全。

      关于使用noexcept的唯一合理的地方是在你的类型中提供移动构造函数或移动赋值时,并且只有当你觉得需要自己定义它们而不是依赖于编译器生成的版本时。这很有用,因为一些STL容器操作会更快,因为它们在实现中使用函数std :: move_if_noexcept。

      我还建议{@ 3}}详细了解noexcept功能。