3

私は現在、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-…

sample::operator- を noexcept として宣言しても安全ですか? (戻り時にコンストラクターを呼び出していることを考慮して)

編集: 質問の中心部分が明確ではなかったように思われるため、コード セクションを更新しました…</p>

4

2 に答える 2

2

編集後:の実装はoperator-例外をスローしないことが保証されているため(少なくとも、としてマークを付けた場合operator*noexcept、したがって、としてマークを付けるのは安全noexceptです。私はあなたの懸念を本当に理解していません、それで私は質問の理由を逃しているかもしれません。潜在的なコピーまたは移動の構築を含むすべての操作は、明示的にマークされていnoexceptます...問題はどこにありますか?


明示的にマークを付けない限りnoexcept、その資格はありません。さて、の実装operator*コピーコンストラクターによっては、実際にはスローされない場合がありますが、それではうまくいきませんnoexcept

コピーコンストラクターの時点で、定義しない場合、暗黙的に宣言されたコピーコンストラクターはnoexcept、タイプのすべてのメンバーがnoexcept(ここでも、スローしないだけでなく、その資格)

于 2012-03-17T20:33:38.133 に答える
1

あなたの質問は、「それは安全ですか?」です。「例外をスローしないという理由だけで、一部の関数を noexcept として宣言することは理にかなっていますか?」と尋ねたいと思います。

厳密に言えば、noexcept が提供するものは 2 つあります。

  1. 関数が noexcept として宣言されているかどうかは、誰でもコンパイル時にチェックできます。(これは、実際には 1 つの std 関数でのみ有用です: move_if_noexcept)
  2. それでも関数が例外をスローしようとしても、関数から抜け出さないという実行時の保証が得られます (代わりに std::terminate が呼び出されるため)。

さらに興味深いことに、noexcept が提供しないものをリストすると、次のようになります。

  1. 関数が実際にスローしない場合のコンパイル時の自動チェック
  2. さらに重要なことに、「例外的な安全保証」は提供されません。

noexcept を学習する際に 2 番目の項目が見落とされることが多いと思います。失敗しない保証を提供したい場合 (関数は失敗する可能性がありますが、スローしない可能性があるため、これはスローしない保証とは異なることに注意してください)、単純にそれを関数に実装して何もスローせず、どこかに文書化することができます。関数を noexcept としてマークする必要はありません。とにかく、失敗しない例外の安全性を提供します。

noexcept を使用する唯一の適切な場所は、型にムーブ コンストラクターまたはムーブ代入を提供するときであり、コンパイラによって生成されたバージョンに依存するのではなく、それらを自分で定義する必要があると思われる場合に限ります。一部の STL コンテナー操作は、実装で関数 std::move_if_noexcept を使用するため、より高速に動作するため、これは便利です。

noexcept 機能の詳細については、こちらの記事もお勧めします。

于 2012-07-05T09:00:19.317 に答える