8

副作用のあるコピーコンストラクターを持つ例外クラスについて考えてみます。

コンパイラはここでコピーコンストラクタの呼び出しをスキップできますか?

try {
    throw ugly_exception();
}
catch(ugly_exception) // ignoring the exception, so I'm not naming it
{ }

これはどうですか:

try {
    something_that_throws_ugly_exception();
}
catch(ugly_exception) // ignoring the exception, so I'm not naming it
{ }

(はい、これはすべて非常に醜いことを知っています、これは別の質問に触発されました)

4

3 に答える 3

9

はい、それは投げるときと捕まえるときの両方で取り除くことができます。キャッチの場合、catch句で指定されたタイプが例外オブジェクトのタイプと同じ(cv-qualificationsを除く)である場合にのみ、それを削除できます。より正式で詳細な説明については、C ++ 11 12.8/31を参照してください。

...コピーの省略と呼ばれるこのコピー/移動操作の省略は、次の状況で許可されます(複数のコピーを削除するために組み合わせることができます)。

..。

  • throw-expressionで、オペランドが不揮発性の自動オブジェクト(関数またはcatch-clauseパラメーターを除く)の名前であり、そのスコープが最も内側の囲んでいるtry-block(存在する場合)の終わりを超えない場合)、オペランドから例外オブジェクト(15.1)へのコピー/移動操作は、自動オブジェクトを例外オブジェクトに直接構築することで省略できます。

..。

  • 例外ハンドラの例外宣言(15節)が例外オブジェクト(15.1)と同じタイプのオブジェクト(cv-qualificationを除く)を宣言する場合、例外宣言を次のように扱うことにより、コピー/移動操作を省略できます。例外宣言によって宣言されたオブジェクトのコンストラクタとデストラクタの実行を除いて、プログラムの意味が変更されない場合の例外オブジェクトのエイリアス。
于 2011-09-13T12:21:08.567 に答える
4

これは特に許可されていると思います。C ++ 03の場合、15.1/3は次のように述べています。

throw-expressionは、例外オブジェクトと呼ばれる一時オブジェクトを初期化します。

そして12/15は言う:

参照(12.2)にバインドされていない一時クラスオブジェクトが同じcv-unqualifiedタイプのクラスオブジェクトにコピーされる場合、一時オブジェクトをターゲットに直接構築することにより、コピー操作を省略できます。省略されたコピー

したがって、飛行中の例外が保持される秘密の隠れ場所は、標準によって一時的なものとして定義されているため、コピーの省略に有効です。

編集:おっと、私は今さらに読んだ。15.1 / 5:

一時オブジェクト(12.2)の使用に関連するコンストラクタとデストラクタの実行を除いて、プログラムの意味を変更せずに一時オブジェクトの使用を排除できる場合、ハンドラの例外は引数を使用して直接初期化できます。スロー式の。

あまり明確になりません。

実際にそうなるかどうか...catch句が例外を再発生させる場合(そうする可能性のある非表示コードを呼び出した場合を含む)、実装では「例外オブジェクトと呼ばれる一時オブジェクト」がまだ存在している必要があります。したがって、そのコピーの省略が可能な場合には、いくつかの制限がある可能性があります。ただし、空のcatch句では再起動できないことは明らかです。

于 2011-09-13T12:22:44.800 に答える
0

はい。参照catchによって例外をキャッチした場合、コピーはありません(まあ、それは定義によるものです)。

しかし、それはあなたの質問ではないと思います。あなたが書いたコードは、参照の言及なしに意図的に書かれていると思います。その場合は、はい、この場合でも、コピーを省略できます。実際には、の変数の初期化は理論的にcatch直接初期化です。また、直接初期化でのコピーは、可能な場合はコンパイラーによって省略できます。

C++03§8.5/14読み取り、

[...]場合によっては、実装は、初期化されるオブジェクトに直接中間結果を構築することにより、この直接初期化に固有のコピーを排除することが許可されます。

于 2011-09-13T12:11:14.833 に答える