次のクラスがあるとします。
class MyClass {
public:
int value() const {
return value_;
}
private:
volatile int value_;
};
value() メンバー関数も最適化されないように揮発性としてマークする必要がありますか、それとも書かれているとおりに大丈夫ですか? ありがとう。
次のクラスがあるとします。
class MyClass {
public:
int value() const {
return value_;
}
private:
volatile int value_;
};
value() メンバー関数も最適化されないように揮発性としてマークする必要がありますか、それとも書かれているとおりに大丈夫ですか? ありがとう。
それはどのように機能するかに完全に類似してconst
います。
オブジェクトがあるconst
場合、マークされたメンバー関数のみconst
が呼び出し可能です。
など...
オブジェクトがあるvolatile
場合、マークされたメンバー関数のみvolatile
が呼び出し可能です。
オブジェクト自体が でない限りvolatile
、関数がそうであるかどうかに違いはありません。
ただし、マルチスレッドとvolatile
は何の関係もないことに注意してください。また、スレッドセーフ コードの作成には役立ちません。並行性に関連するものには不適切なツールです。
心配なのは、MyClasscがあるかどうかです。次に、c.value();を呼び出します。数回、コンパイラーは、c.value()が同じ値を返すと考える場合があります(変更された可能性がある場合でも)。
コンパイラが関数の内部を認識しない別のコンパイルモデルでは、副作用([*])がないと想定できないため、関数へのさまざまな呼び出しを削除できません。コンパイラーが関数の定義を確認し、コードをインライン化する場合、メンバーはそのメンバーであるvolatile
ことが確認されるため、最適化することもできません。
[*]一部のコンパイラ(つまりgcc)には、関数への複数の呼び出しを可能にするために、関数が純粋であること(つまり、副作用がなく、出力は提供された引数のみに依存する)を通知するために使用できる特別な属性があります。たとえば、次のループで最適化されます。
const char* lit = "Literal";
int sum = 0;
for ( int i = 0; i < strlen(lit); ++i ) {
sum += lit[i];
}
ライブラリで純粋としてマークされているためstrlen
、コンパイラは値をキャッシュし、ループを次のように変換します。
const char* lit = "Literal";
int sum = 0;
int __len = strlen(lit);
for ( int i = 0; i < __len; ++i ) {
sum += lit[i];
}
ただし、ライブラリは、これを実行できることをコンパイラに具体的に通知する必要があります。属性の形で追加情報がなければ、何も想定できずstrlen
、ループの各反復で関数を呼び出す必要があります。
value()メンバー関数も、最適化されないように揮発性としてマークする必要がありますか、それとも記述どおりに問題ありませんか?
メンバー関数をvolatileとしてマークしても、最適化されているかどうかには影響しません。書かれている通りで大丈夫です。
心配なのは、MyClasscがあるかどうかです。次に、c.value();を呼び出します。数回、コンパイラーは、c.value()が同じ値を返すと考える場合があります(変更された可能性がある場合でも)。
あなたが望んでいるのはアトミック変数について学ぶことのように聞こえます。std::atomicを見てください。
揮発性について本当に学びたい場合は、このペーパーを読んでください:http ://www.cs.utah.edu/~regehr/papers/emsoft08-preprint.pdf
定数および揮発性メンバー関数 (C++ のみ)
const 修飾子で宣言されたメンバー関数は、定数および非定数オブジェクトに対して呼び出すことができます。非定数メンバー関数は、非定数オブジェクトに対してのみ呼び出すことができます。同様に、volatile 修飾子で宣言されたメンバー関数は、volatile および nonvolatile オブジェクトに対して呼び出すことができます。非揮発性メンバー関数は、非揮発性オブジェクトに対してのみ呼び出すことができます。