揮発性と可変性の違いについて質問があります。私は、2つの両方がそれが変更される可能性があることを意味することに気づきました。ほかに何か?それらは同じものですか?違いは何ですか?それらはどこに適用できますか?なぜ2つのアイデアが提案されているのですか?それらを別の方法で使用する方法は?
どうもありがとう。
回答:
mutableフィールドもを通じてアクセスされたオブジェクトに変更することができるconstポインタまたは参照、またはでconstコンパイラは、R / Oメモリにそれを隠ししない知っているので、オブジェクト。volatile場所は、コンパイラが最適化などに値が「多分持つことができないという不正な仮定の下で、その値の割り当てを登録していない知っているので、コンパイラは(例えば、いくつかのカーネルレベルのドライバ)について知らないコードによって変更することができるものですそのレジスタに最後にロードされてから「変更されました」。非常に異なる種類の無効な最適化を停止するために、非常に異なる種類の情報がコンパイラーに提供されます。
volatileオブジェクトがコンパイラの知識の範囲外で変更される可能性があることを意味するだけでなく、オブジェクトへの書き込みが役に立たないように見えても、コンパイラがオブジェクトへの書き込みを排除できないことも意味します。たとえば、次のx = 1; x = 0; 場合にx揮発性であり、コンパイラは、(ハードウェアレベルで有意であるかもしれない)の両方の書き込み操作を放出しなければなりません。ただし、非揮発性オブジェクトの場合、コンパイラは1使用されないため、書き込みに煩わされないことを選択できます。
const、およびvolatile!オブジェクトを変更することはできませんが、背後で変更することはできます。
mutable:mutableキーワードは、それを囲むconstステートメントをオーバーライドします。constオブジェクトの可変メンバーは変更できます。
volatile:volatileキーワードは、実装に依存する修飾子であり、変数を宣言するときに使用されます。これにより、コンパイラーはこれらの変数を最適化できなくなります。Volatileは、コンパイラが実行する可能性のある最適化と競合する可能性のある、予期しない方法で(つまり、割り込みによって)値が変更される可能性のある変数とともに使用する必要があります。
Volatile should be used with variables whose value can change in unexpected ways、我々はランダムでそれを使用することを好むでしょうか?
それらは間違いなく同じものではありません。ミュータブルはconstと相互作用します。constポインターがある場合、通常はメンバーを変更できません。ミュータブルはそのルールに例外を提供します。
一方、揮発性は、プログラムによって行われた変更とはまったく関係がありません。これは、コンパイラの制御が及ばない理由でメモリが変更される可能性があることを意味します。したがって、コンパイラは毎回メモリアドレスを読み書きする必要があり、コンテンツをレジスタにキャッシュできません。
T、に格納し、const T*そこから読み取ることができます。そのオブジェクトを作成すると、書き込みを試みたことがなくても、volatileそのアドレスをに格納するconst T*ことは失敗します。 volatileプログラムコードからの変更/修正/メモリ書き込みは完全に直交しています。
違いについての大まかな、しかし効果的な考え方は次のとおりです。
volatilebytes_received、mutablereference_count。
volatileは、マルチスレッドアプリケーションを処理するときにも非常に役立つことを付け加えておきます。つまり、メインスレッド(main()が存在する場所)があり、変数「app_running」がtrueの間回転し続けるワーカースレッドを生成します。main()は、「app_running」がtrueかfalseかを制御するため、「app_running」の宣言にvolatile属性を追加しない場合、コンパイラがセカンダリスレッドによって実行されるコードで「app_running」へのアクセスを最適化すると、main( )「app_running」をfalseに変更する可能性がありますが、値がキャッシュされているため、セカンダリスレッドは実行を継続します。LinuxとVisualC ++でgccを使用しても同じ動作が見られます。「app_running」宣言に入れられた「volatile」属性が問題を解決しました。そう、
volatileオブジェクトは、CPUをまったく含まないプロセスによっても変更される可能性があります。たとえば、通信ペリフェラルのバイト受信レジスタは、バイトの受信時にそれ自体をインクリメントできます(これにより、割り込みがトリガーされることもあります)。もう1つの例は、ペリフェラルの保留中の割り込みフラグレジスタです。