web-dev-qa-db-ja.com

C ++のvolatileとmutable

Volatileとmutableの違いについて質問があります。 2つとも変更できることを意味していることに気付きました。ほかに何か?それらは同じものですか?違いは何ですか?それらはどこに適用できますか?なぜ2つのアイデアが提案されているのですか?別の方法でそれらを使用する方法?

どうもありがとう。

82
skydoor

mutableフィールドは、constポインターまたは参照を介してアクセスされるオブジェクト、またはconstオブジェクト内でも変更できるため、コンパイラーはR/Oメモリ。 volatileの場所は、コンパイラーが知らないコード(たとえば、カーネルレベルのドライバー)によって変更できる場所です。したがって、コンパイラーは、たとえば値がそのレジスタに最後にロードされてから「変更されていない可能性がある」という無効な仮定の下で、その値のレジスタ割り当て。非常に異なる種類の無効な最適化を停止するために、コンパイラに非常に異なる種類の情報が提供されます。

107
Alex Martelli

mutable:mutableキーワードは、囲むconstステートメントをオーバーライドします。 constオブジェクトの可変メンバーは変更できます。

volatile:volatileキーワードは実装に依存する修飾子であり、変数を宣言するときに使用され、コンパイラーがそれらの変数を最適化できないようにします。揮発性は、コンパイラが実行する可能性のある最適化と競合する可能性のある、予期しない方法で(つまり、割り込みを介して)値が変化する可能性がある変数で使用する必要があります。

ソース

27
xian

それらは間違いなく同じものではありません。 Mutableはconstと対話します。 constポインターがある場合、通常はメンバーを変更できません。 Mutableは、そのルールの例外を提供します。

一方、揮発性は、プログラムによる変更とはまったく関係ありません。これは、コンパイラが制御できない理由でメモリが変更される可能性があるため、コンパイラは毎回メモリアドレスを読み書きする必要があり、レジスタにコンテンツをキャッシュできないことを意味します。

22
Ben Voigt

違いの大雑把だが効果的な考え方は次のとおりです。

  • コンパイラは、可変オブジェクトがいつ変更されるかを知っています。
  • コンパイラは、volatileオブジェクトがいつ変更されるかを知ることができません。
17

mutableとマークされた変数は、constと宣言されたメソッドで変更することができます。

volatileとマークされた変数は、コードが指示するたびに変数を読み書きする必要があることをコンパイラーに指示します(つまり、変数へのアクセスを最適化できません)。

10
Kyle Lutz

Volatileは、マルチスレッドアプリケーションを扱うときにも非常に便利です。つまり、メインスレッド(main()が存在する場所)があり、変数 "app_running"がtrueである間スピンを続けるワーカースレッドを生成します。 main()は、「app_running」がtrueまたはfalseであるかどうかを制御するため、volatile属性を「app_running」の宣言に追加しない場合、コンパイラがセカンダリスレッドによって実行されるコードの「app_running」へのアクセスを最適化する場合、main( )は「app_running」をfalseに変更する可能性がありますが、値がキャッシュされているため、セカンダリスレッドは実行を続けます。 LinuxとVisualC++でgccを使用して同じ動作を確認しました。 「app_running」宣言に含まれる「volatile」属性が問題を解決しました。したがって、これは、そのような変数の値を変更する際にハードウェア割り込みやカーネルが呼び出されないシナリオです。

4
BinCoder