2
int main()
{
    const int maxint=100;//The program will crash if this line is put outside the main
    int &msg=const_cast<int&>(maxint);  
    msg=200;  
    cout<<"max:"<<msg<<endl; 
    return 0;
}

'const int maxint = 100;'の場合、関数は正常に実行されます。定義はmain関数内に配置されますが、外部に配置するとクラッシュして「アクセス違反」というエラーメッセージがポップアップ表示されます。

ある種の「未定義動作」だと誰かが言ったのですが、正確な答えと、constキャストを安全に使用する方法を知りたいですか?

4

3 に答える 3

9

それらは正しいです、それは未定義の振る舞いです。変数の値を変更することは許可されていません。これは、何かconstの本質を捨てる危険性があります。実際にはそうではないことをよく知っています。constconst

コンパイラーmaxintは、それが変更されていることconst、および変更されるべきではないことを認識しているため、アドレスを指定する必要さえありません。maxint適切と思われる場合は、のすべての用途を100に置き換えることができます。また、Matteo Italiaが指摘しているように、メモリの読み取り専用の部分に定数を入れるだけかもしれません。これはおそらくあなたに起こっていることです。そのため、変更すると未定義の動作が発生します。

変数の性質を安全に捨てることができる唯一の方法constは、変数が実際constにはない場合ですが、const修飾子はconst次のように非変数に追加されました。

int f(const int& x) {
    int& nonconst = const_cast<int&>(x);

    ++nonconst;
}

int blah = 523;

f(blah); // this is safe

const int constblah = 123;

f(constblah); // this is undefined behaviour

完全にコンパイルされるこの例について考えてみてください。

int f(const int& x) {
    int& nonconst = const_cast<int&>(x);

    ++nonconst;
}

int main() {
    f(4); // incrementing a number literal???
}

変数が元々あるかどうかを実際に判断する方法がないため、使用const_castが非常に危険であることがわかりますconst。可能な場合は使用を避ける必要があります(関数では、パラメーターconst_castを受け入れないだけです)。const

于 2011-12-29T02:09:56.563 に答える
5

const(可変メンバーを除いて)オブジェクトを変更すると、(C ++ 03標準からの)未定義の動作が発生します。

7.1.5.1/4「cv-qualifiers」

可変(7.1.1)と宣言されたクラスメンバーを変更できることを除いて、constオブジェクトをその存続期間(3.8)中に変更しようとすると、未定義の動作が発生します。

上記の未定義の動作は、次の標準のセクションで具体的に示されていconst_castます。

5.2.11/7「コンストキャスト」

[注:オブジェクトのタイプによっては、const-qualifier68)をキャストするconst_castから生じるポインター、左辺値、またはデータメンバーへのポインターを介した書き込み操作により、未定義の動作(7.1.5.1)が発生する場合があります。]

したがって、const実際にはそうではないオブジェクトへのポインタまたは参照がある場合はconst、そのオブジェクトへの書き込みは許可されますが(constnessをキャストすることにより)、オブジェクトが実際にである場合は許可されませんconst

constたとえば、コンパイラはオブジェクトを読み取り専用ストレージに配置することが許可されています。ただし、そうする必要はなく、クラッシュしないテストコードには当てはまらないようです。

于 2011-12-29T02:25:59.300 に答える
0

あなたは、そうではないことが知られているオブジェクトの恒常性を捨てることだけが許されていますconst。たとえば、インターフェイスがconstポインタまたはconst参照を使用してオブジェクトを渡す場合がありますが、オブジェクトconstを変更する必要がない、または変更する必要があるオブジェクトを渡しました。この場合、恒常性を捨てることは正しいことかもしれません。

一方、ずっとあったオブジェクトの不変性を捨てると、const深刻な問題が発生する可能性があります。このオブジェクトにアクセスするとき、特に書き込みを行うとき、システムはあらゆる種類の奇妙なことを引き起こす可能性があります。動作は定義されていません。 (C ++標準による)特定のシステムでは、たとえばアクセス違反が発生する可能性があります(オブジェクトのアドレスが読み取り専用領域に配置されているため)。

別の応答にもかかわらずconst、アドレスが何らかの方法で取得および使用された場合、オブジェクトはアドレスを割り当てる必要があることに注意してください。コードでは、const_cast<int&>(maxint)式は基本的に定数intのアドレスを取得します。このアドレスは、読み取り専用としてマークされたメモリ領域に格納されているようです。コードスニペットの興味深い点は、明らかに特に最適化をオンにする場合は機能します。コードは非常に単純なので、変更された場所が実際には使用されておらず、実際にメモリの場所を変更しようとはしません。この場合、アクセス違反は報告されません。これは、定数が関数内で宣言されている場合に明らかに当てはまります(ただし、定数はスタック上にある場合もあり、通常は読み取り専用としてマークできません)。コードのもう1つの潜在的な結果は、(定数が関数内で宣言されているかどうかに関係なく)実際に変更され、場合によっては100として読み取られ、他のコンテキスト(何らかの方法でアドレスを含む)では200として読み取られることです。

于 2011-12-29T02:25:20.640 に答える