web-dev-qa-db-ja.com

assertとstatic_assertの違いは何ですか?

static_assertがコンパイル時にアサーションを作成し、assert-実行時にアサーションを作成することは知っていますが、実際の違いは何ですか?私が理解している限り、これらのコードは次のようなコードです。

if (condition == false) exit();
  • onlystatic_assertが機能する場所、またはonlyassertの例を誰かに教えてもらえますか?
  • 単純なifステートメントでは実行できないことは何ですか?
  • それらを使用することは悪い習慣ですか?
49
Oleksiy

あなたは3つの質問をするので、私はそれらのそれぞれに答えようとします。

  • onlystatic_assertが機能する場所、またはonlyassertの例を誰かに教えてもらえますか?

static_assertは、コンパイル時にコード内のロジックをテストするのに適しています。 assertは、実行時に常に1つの結果が得られるはずであるケースをチェックするのに適していますが、予期しない状況で何らかの理由で予期しない結果が生じる可能性があります。たとえば、メソッドに渡されたポインタがassertであるかどうかを判断するためにnullを使用する必要があるのは、そのようなことが発生しないように思われる場合のみです。 static_assertはそれをキャッチしません。

  • 彼らは単純なifステートメントでは実行できないことをしていますか?

assertはプログラムの実行を中断するために使用できるため、適切なエラーメッセージであるifを使用し、プログラムの実行を停止して同様の効果を得ることができますが、assertはその場合は少し簡単です。 static_assertはもちろんコンパイル問題の検出にのみ有効ですが、ifはプログラムで有効でなければならず、コンパイル時に同じ期待値を評価することはできません。 (ただし、ifを使用すると、実行時にエラーメッセージを出力できます。)

  • それらを使用することは悪い習慣ですか?

どういたしまして!

51
patrickvacek

static_assertcompilationを指定されたメッセージで失敗させることを目的としていますが、従来のassertはプログラムの実行を終了することを目的としています。

19
Nicola Musatti

かしこまりました。

  • 静的条件に違反した場合にコンパイルを失敗させたい場合は、_static_assert_のみが機能します:static_assert(sizeof(void*) != 3, "Wrong machine Word size"); *動的アサーションのみが動的条件をキャッチできます:assert(argc == 1);

  • 単純なifステートメントは、有効でコンパイル可能でなければなりません。静的アサーションはコンパイルの失敗を引き起こします。

  • 番号。

*)実用的な例は、int x; std::move<int&&>(x)などの一般的なテンプレート構造の乱用を防ぐことです。

7
Kerrek SB

それらを使用することは悪い習慣ですか?

乱用された場合、はい、特にassert

1つの乱用は、アクティブなassertステートメントに依存しています。 assertを定義してコンパイルすると、NDEBUGは何もしないため、assertに依存して何かを行うことはできません。多くの場合、量産コードはNDEBUGが定義された状態でコンパイルされ、これらのassertステートメントが確実に消えるようにします。

1〜2日以上存続しない1回限りのプログラムを作成しているのでない限り、ユーザー入力の検証に使用すべきではありません。ユーザーはコードがどこで失敗したかを気にせず、出力されるメッセージは多くのユーザーにとって外国語のように見えます。エラーの修正方法はユーザーに通知されません。また、設計上、非常に許容範囲が広くなっています。ユーザー入力エラーへの応答として発行されるメッセージは、問題を修正する方法をユーザーに通知するメッセージである必要があります。メッセージの後の最善のアクションは、ユーザーにエラーを修正する方法を提供することです。それができない場合、そして実行可能な唯一の応答がプログラムを終了することである場合、プログラムは完全に終了するはずです。設計上、assertは正常にシャットダウンされません。 abort()ではなくexit()を呼び出します。

多くのマシンでabort()を使用すると、コアダンプが生成されます。コアダンプは、プログラマにとって素晴らしいエラーメッセージです。コアダンプを使用すると、プログラマーはデバッガーを使用して、問題の原因を詳細に確認できます。 abort()の欠点は、物事がクリーンアップされないことです。中止すると、「自動または静的ストレージ期間のオブジェクトのデストラクタを実行せず、atexit()に渡された関数を呼び出さずにプログラムを終了します。」

結論:assertを使用してプログラミングエラーをテストすることは問題ありませんが、本番環境以外の設定でのみ可能です。他のものを使用して、ユーザーエラーをテストします。

4
David Hammen

static_assertはコンパイラ指令です。コンパイル時に型情報を確認できます。コンパイルが失敗し、ほとんどのIDEでキャッチされ、IDEのエラーウィンドウに表示されるエラーメッセージが生成されます。

static_assert(sizeof(int) == 4,"int should be 4 bytes");

assertはランタイム用で、変数の値を確認できます。アサーションが失敗すると、アサーションがトリガーされます。これにより、一部のオペレーティングシステムでは実行時に表示されるエラーメッセージボックスが表示されます(実装に依存するアサート)。

assert(("mypointer  should never be null!", mypointer != nullptr));
1
Yochai Timmer