5

私は次のコードを持っています:

const int k=1;
    int *p=const_cast<int *>( &k);
    cout<<"k before="<<*p<<endl;
    *p=10;
    *const_cast<int *>( &k)=12;
    cout<<"k after="<<k<<endl;

出力は:

k before=1
k after=1

なぜここでキャストが機能しないのですか?

4

3 に答える 3

12

const_castキャストしてから値に書き込むと、未定義の動作が発生します。constここで見たように、何もしないことは有効な動作です。

あなたの特定の例では、おそらく起こったことは、コンパイラがストレージクラスでk宣言されてconstいることを確認し、(合法的に)変更できないことを認識し、置換することです。

cout<<"k after="<<k<<endl;

cout<<"k after="<<1<<endl;

最適化をオフにすると、異なる結果が得られる場合と得られない場合があります。

キャストアウェイconstが未定義の動作を呼び出すまさにその理由は、コンパイラーがこのような最適化を自由に行えるようにするためです。const変数を非変数に自由にキャストしてconst書き込むことができればconst、コンパイラーにとってはまったく意味がありません。

于 2012-01-21T15:42:39.080 に答える
4

あなたがしているのは未定義動作です。次のような変数を変更することはできません。const

于 2012-01-21T15:43:09.033 に答える
2

const_castconst通常、元々。として定義されていないオブジェクトへのポインタを受け取った場合に使用されconstます。(あなたの場合のように)オブジェクトが元々として定義されていた場合const、それを変更しようとすると未定義の動作が発生します。がないconst_castと、コンパイラーはそれを実行しようとさえしません(コードはコンパイルされません)。

ただし、キャストはコンパイラーに、自分が何をしているかを確実に理解し、本当に安全であることを伝えます。したがって、コンパイラーは、通常のようなエラー/警告メッセージを表示するのではなく、シャットダウンして、指示したとおりに実行する必要があります。行う。残念ながら、この場合、実行していることは実際には安全ではありませんが、コンパイラーにシャットダウンして実行するように指示しているため、(少なくともほとんどのコンパイラーでは)警告は表示されません。

あなたが何をすべきかについては、あなたkが本当にconstであるかどうかを決定することになります。本当に変更する必要がある場合は、通常の(非const)変数として定義する必要があります。少量の特定のコードのみがそれを変更できるようにしたい場合は、(1つの可能性として)それを小さなクラスにプライベートにすることができます。

class my_int { 
    int k;
public:
    my_int() : k(1) {}

    do_mod() { k = 10; }

    operator int() { return k; }
};

今、直接do_mod変更することができkます。他のコードは、my_intオブジェクトをあたかもそれであるかのように使用できますが、intその値を変更することはできません。本質的に、それは右辺値のように機能します。

公平を期すために、キャストを実際に実行しようとすると、他のコードがの値を変更する可能性があることを指摘しておく必要がありkます。Bjarneが言ったように、C ++の保護メカニズムは、意図的な破壊ではなく、事故を防ぐことを目的としています。

于 2012-01-21T16:36:54.203 に答える