11

私は volatile メンバー関数について読んでいて、メンバー関数がconst と volatileの両方になることができるという断言に出くわしました。私はそのようなものの実際の使用を得ませんでした。メンバー関数を const と volatile として一緒に使用する実際の使用に関する経験を共有してください。

同じことをテストするために小さなクラスを書きました:

class Temp
{
public:

    Temp(int x) : X(x)
    {
    }

    int getX() const volatile
    {
        return X;
    }

    int getBiggerX()
    {
        return X + 10;
    }
private:
    int X;
};

void test( const volatile Temp& aTemp)
{
    int x = aTemp.getX();
}

int main(int argc, char* argv[])
{
    const volatile Temp aTemp(10);
    test(aTemp);

    return 0;
}
4

6 に答える 6

13

揮発性メンバー関数の実用的な例を求めました。私想像できる唯一の状況は非常に低レベルであるため、最初にメンバー関数を使用することを検討せず、揮発性参照によってアクセスされるデータメンバーを持つ単純な構造体であるため、考えられません。

ただし、質問に答えるために const volatile 関数を入れましょう。それぞれ 4 バイトの 2 つの整数を含むアドレス 0x378h のポートがあるとします。それからあなたは書くことができます

struct ints {
    int first;
    int second;
    int getfirst() const volatile {
        return first;
    }

    int getsecond() const volatile {
        return second;
    }
      // note that you could also overload on volatile-ness, just like
      // with const-ness
};

// could also be mapped by the linker. 
ints const volatile &p = *reinterpret_cast<ints*>(0x378L);

あなたは述べています

私はそれらを変更していませんが、この抽象的なセマンティクス以外の別のことが変更される可能性があります。したがって、常にそのアドレスから実際のロードを行います。

実際には、volatileは、オブジェクトの値が最後に格納された値ではない可能性があることを示しますが、実際には不明であり、外部 (コンパイラによって監視できない) 条件によってその間に変更された可能性があります。したがって、揮発性オブジェクトから読み取る場合、コンパイラは正確な抽象セマンティクスをエミュレートする必要があり、最適化は実行しません。

a = 4;
a *= 2; 
  // can't be optimized to a = 8; if a is volatile because the abstract
  // semantics described by the language contain two assignments and one load.

以下はすでに何をするかを決定してvolatileいます。すべてが1.9標準の中にあります。それが話しているパラメータは、何らかの型の sizeof のように、実装で定義されたものです。

この国際標準のセマンティック記述は、パラメータ化された非決定論的抽象マシンを定義します。この国際規格は、適合する実装の構造に要件を課していません。特に、抽象マシンの構造をコピーまたはエミュレートする必要はありません。むしろ、以下で説明するように、抽象マシンの観察可能な動作をエミュレートする (のみ) ために、適合する実装が必要です。[...]

整形式プログラムを実行する適合実装は、同じプログラムと同じ入力を持つ抽象マシンの対応するインスタンスの可能な実行シーケンスの 1 つと同じ観測可能な動作を生成するものとします。[...]

抽象マシンの観察可能な動作は、揮発性データへの読み取りと書き込み、およびライブラリ I/O 関数の呼び出しのシーケンスです。

于 2009-03-17T17:02:47.000 に答える
1

メンバー関数でconstとvolatileの両方が必要になる可能性があると私が考えることができる状況の1つは、関数が論理的にconstであるが、実際には共有メモリの場所にあるデータキャッシュを変更する必要がある組み込みシステムの状況です(たとえば、オンデマンドでビットマップを作成し、同じビットマップがすぐに再び必要になった場合に備えてビットマップをキャッシュします)。確かにあまり頻繁には出てきません。

于 2009-03-18T03:10:00.437 に答える
1

const volatile としてマークされたオブジェクトは、宣言されているコードによって変更できません。const 修飾子が原因でエラーが発生します。修飾子の揮発性部分は、コンパイラがオブジェクトに関してコードを最適化できないことを意味します。

組み込みシステムでは、これは通常、ハードウェアによって読み取られて更新されるハードウェアレジスタにアクセスするために使用されるため、コードを介してレジスタに書き込むことができても意味がありません。例として、シリアル ポートのステータス レジスタがあります。文字が読み取られるのを待っている場合など、さまざまなビットがステータスを示します。このステータス レジスタへの各読み取りは、シリアル ポート ハードウェアで他に何が発生したかに応じて、異なる値になる可能性があります。ステータス レジスタに書き込むことは意味がありませんが、レジスタの各読み取りがハードウェアの実際の読み取りになることを確認する必要があります。

以下はイラストです:

//We assume that the below declared pointers
//point to the correct
//hardware addresses
unsigned int const volatile *status_reg;
unsigned char const volatile *recv_reg;

#define CHAR_READ 0x01

int get_next_char()
{
    while((*status_reg & CHAR_READ) == 0);
    return *recv_reg;
}

お役に立てれば。

よろしくサンディパン・カルマカール。

于 2013-03-17T16:12:19.987 に答える
1

「const volatile」関数を使用する理由は、継承を「保護」する理由と同じだと思います。文法上許可されているので、その意味を考えた方がよいでしょう。

于 2009-03-17T18:26:06.397 に答える