前提・実現したいこと
c++で、int型変数aとaを参照先に持つポインタptrをデータメンバーとして持ったクラスtestを宣言しました。
ptrは、メンバイニシャライザにて参照先をaにしています。
main内でconst testオブジェクトobjを宣言したところ、*obj.ptr = 0といった形でconstオブジェクトであるにもかかわらずaに代入ができてしまいます。
なぜエラーが出ずに代入できるのかがわかりません。
該当のソースコード
c++
1#include <iostream> 2 3struct test{ 4 int a; 5 int * ptr; 6 test() : a(0), ptr(&a){} 7}; 8 9int main(){ 10 const test obj; 11 *obj.ptr = 10; // 代入ができてしまう 12 13 return 0; 14}
どのような挙動になると思ったか
objはconstなオブジェクトなので、objのサブオブジェクトはすべてconst修飾されたものとして動作するように思っています。
すなわち、int aならばconst int a、int * ptrならばint * const ptrとして処理されると考えていました。
このままではコンストラクタの時点で「constな変数を参照しないポインタがconstな変数を参照している」状態に陥り、コンパイル時にその件についてのエラーが出力されると思いました。
どのような挙動になったか
constを参照しないポインタだと思っていたptrが、constだと思っていたaを参照できてしまいました。
その上、*obj.ptr = 10;などとすることで、const修飾されたはずのaに代入できてしまいました。
obj.a = 10;などでは予想通り変更できませんでした。
なぜエラーが出ず、代入ができるのでしょうか。
試したこと
メンバイニシャライザを使わず、先に構築を行いそこに代入する形を取ってみました。
c++
1#include <iostream> 2 3struct test{ 4 int a; 5 int * ptr; 6 test(){ 7 a = 0; 8 ptr = &a; 9 } 10}; 11 12int main(){ 13 const test obj; 14 *obj.ptr = 10; 15 16 return 0; 17}
これも同じくコンパイルが通ります。
サブオブジェクトがconst修飾されているならばコンストラクタ内で代入ができなさそうなものですが、問題なく代入できているようで、余計混乱しました。
これが通るということは、「constオブジェクトがサブオブジェクトをconst修飾するようにはたらく」という前提が間違っていたのでしょうか。
もしくは、const修飾されるのは確かで、しかし「constは書き換えができない」という私の認識が間違っていたのでしょうか。
補足情報
使っている言語はC++17で、コンパイラはgcc-8.2.0です。
回答1件
あなたの回答
tips
プレビュー