9

次のような例外クラスがあります。

#include <exception>

struct InvalidPathException : public std::exception
{
   explicit InvalidPathException() {}
   const char* what() const;
};

const char*
InvalidPathException::what() const {
    return "Path is not valid";
}

-Wall -std = c++0xを使用してGCC4.4でコンパイルする場合

エラー:'virtual const char * InvalidPathException :: what()const'のスロー指定子が緩い

エラー:オーバーライド'virtual const char * std :: exception :: what()const throw()'

確かに例外指定子を持っているstd::exceptionのメソッドをオーバーライドしているので、まったく正しいです。ただし、多くの場合通知されるため、例外指定子を使用しないでください。そして私が理解しているように、それらはC ++ 11で非推奨になっていますが、-std = c++0xを使用したGCCではまだ明らかにされていません。what()throw()

ですから、今のところ最善のアプローチに興味があります。私が開発しているコードでは、パフォーマンスを気にしているので、よく言及されるオーバーヘッドについて心配していますthrow()が、実際には、このオーバーヘッドはそれほど深刻ですか?私what()は、実際に呼び出されたときにのみ問題が発生するだろうと思っていますか?それは、そのような例外がスローされた後だけです(同様に、すべてにthrow()指定子があるstd :: exceptionから継承された他のメソッドの場合)?

あるいは、GCCによって与えられたこのエラーを回避する方法はありますか?

4

1 に答える 1

7

空の仕様は、ウィキペディアthrowが知っているように、呼び出し元のサイトでコンパイラの最適化を実際に有効にするので便利です(技術的な見積もりは手元にありません)。

そして、最適化の機会の理由から、nothrow仕様は、次の標準では非推奨ではなくthrow ()、もはや見た目ではなく、と呼ばれていnoexceptます。ええ、そうです、そしてそれらはわずかに異なった働きをします。

これについては、従来のnothrownoexcept仕様が呼び出し先のサイトでの最適化を禁止する理由についても詳しく説明します。

一般に、throw少なくとも完全に準拠したコンパイラを使用して、所有しているすべての仕様に対して料金を支払います。この点で、GCCは常にそうであるとは限りません。これらthrowの仕様は、空の仕様であっても、実行時にチェックする必要があります。これは、仕様に準拠していない例外が発生した場合throw、スタックの巻き戻しをそのスタックフレーム内で実行する必要があり(したがって、準拠チェックに加えてそのためのコードが必要)、次にstd::unexpected呼び出す必要があるためです。一方、コンパイラーがその関数を呼び出すときに、より多くの仮定を行う可能性があるため、空の仕様ごとに時間/スペースを節約できる可能性があります。 throw私は、プロファイラーだけがあなたの特定のコードが苦しんでいるのか、それとも(!)throws仕様。

実際の問題の回避策として、次のことが機能しますか?

  • 導入#define NOTHROW throw ()して、例外whatやその他のものに使用します。
  • GCCが実装する場合noexcept、を再定義しNOTHROWます。

アップデート

@James McNellisthrow ()が指摘しているように、上位互換性があります。その場合は、throw ()必要な場所だけを使用し、それとは別に、疑わしい場合はプロファイルを使用することをお勧めします。

于 2010-11-26T04:59:59.460 に答える