私は次のコードを持っています:
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
なぜここでキャストが機能しないのですか?
私は次のコードを持っています:
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
なぜここでキャストが機能しないのですか?
const_cast
キャストしてから値に書き込むと、未定義の動作が発生します。const
ここで見たように、何もしないことは有効な動作です。
あなたの特定の例では、おそらく起こったことは、コンパイラがストレージクラスでk
宣言されてconst
いることを確認し、(合法的に)変更できないことを認識し、置換することです。
cout<<"k after="<<k<<endl;
と
cout<<"k after="<<1<<endl;
最適化をオフにすると、異なる結果が得られる場合と得られない場合があります。
キャストアウェイconst
が未定義の動作を呼び出すまさにその理由は、コンパイラーがこのような最適化を自由に行えるようにするためです。const
変数を非変数に自由にキャストしてconst
書き込むことができればconst
、コンパイラーにとってはまったく意味がありません。
あなたがしているのは未定義動作です。次のような変数を変更することはできません。const
const_cast
const
通常、元々。として定義されていないオブジェクトへのポインタを受け取った場合に使用され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 ++の保護メカニズムは、意図的な破壊ではなく、事故を防ぐことを目的としています。