次のコードの出力:
const int i= 1;
(int&)i= 2; // or: const_cast< int&>(i)= 2;
cout << i << endl;
は1です(少なくともVS2012では)
私の質問:
- この動作は定義されていますか?
- コンパイラは常に定数に定義された値を使用しますか?
- コンパイラが最新の割り当ての値を使用する例を作成することは可能ですか?
次のコードの出力:
const int i= 1;
(int&)i= 2; // or: const_cast< int&>(i)= 2;
cout << i << endl;
は1です(少なくともVS2012では)
私の質問:
それは完全に未定義です。定数の値を変更することはできません。
たまたまコンパイラがあなたのコードを次のようなものに変換します
cout << 1 << endl;
しかし、プログラムがクラッシュしたり、何か他のことをしたりする可能性もあります。
警告レベルを十分に高く設定すると、コンパイラはそれが機能しないことを確実に通知します。
この動作は定義されていますか?
このコードの動作は、constオブジェクトを変更しようとするため、C++標準では定義されていません。
コンパイラは常に定数に定義された値を使用しますか?
このような場合にコンパイラが使用する値は、実装によって異なります。C++標準は要件を課していません。
コンパイラが最新の割り当ての値を使用する例を作成することは可能ですか?
コンパイラが値を変更して使用する場合がありますが、信頼性はありません。
答えは、動作が定義されていないということです。
私はなんとかこの決定的な例を設定することができました:
#include <iostream>
using namespace std;
int main(){
const int i = 1;
int *p=const_cast<int *>(&i);
*p = 2;
cout << i << endl;
cout << *p << endl;
cout << &i << endl;
cout << p << endl;
return 0;
}
これは、gcc4.7.2では次のようになります。
1
2
0x7fffa9b7ddf4
0x7fffa9b7ddf4
つまり、2つの異なる値を保持しているのと同じメモリアドレスを持っているようなものです。
最も可能性の高い説明は、コンパイラが定数値をリテラル値に置き換えるだけであるということです。
他の人が言っているように、動作は定義されていません。
完全を期すために、ここに標準からの引用があります:
(§7.1.6.1/ 4)可変(7.1.1)と宣言されたクラスメンバーを変更できることを除いて、constオブジェクトをその存続期間(3.8)中に変更しようとすると、未定義の動作が発生します。[ 例:
[...]
const int* ciq = new const int (3); // initialized as required int* iq = const_cast<int*>(ciq); // cast required *iq = 4; // undefined: modifies a const object
]
オブジェクトという言葉は、この段落が例に示されているように、単純な整数を含むすべての種類のオブジェクトを指していることに注意してください。クラスオブジェクトだけではありません。
この例では、動的ストレージを備えたオブジェクトへのポインターを参照していますが、段落のテキストは、これが自動ストレージを備えたオブジェクトへの参照にも適用されることを明確にしています。
あなたはconst_cast
Cのようなものを使っていcast operator
ます。
使用const_cast
は、いかなる動作も保証するものではありません。
あなたがそれをするならば、それはうまくいくかもしれないし、うまくいかないかもしれません。
(ご存知のC ++でCのような演算子を使用することはお勧めできません)
はい、できますが、次のように、constを読み取り専用として開始し、コンパイル時のconstとして開始しない場合に限ります。
int y=1;
const int i= y;
(int&)i= 2;
cout << i << endl; // prints 2
C ++ constキーワードは誤解を招く可能性があり、constまたは読み取り専用のいずれかです。