前提・実現したいこと
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
プレビュー