質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

1152閲覧

c++ constなオブジェクトのサブオブジェクトをポインタから変更できてしまう

aikawa3311

総合スコア1

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2020/04/29 07:39

前提・実現したいこと

c++で、int型変数aaを参照先に持つポインタ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 aint * 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です。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

pepperleaf

2020/04/29 07:44

多分、詳しい方から、説明が付くと思いますが、、、 > objのサブオブジェクトはすべてconst修飾された なぜ、そう思ったでしょうか? constは、objのみです。
aikawa3311

2020/04/29 07:49

objはconstなtest型であり、obj.a = 10;などのような代入ができなくなるため、そこから「あたかもサブオブジェクトがconst修飾されているようにふるまう」と個人的見解で思っていました。
guest

回答1

0

ベストアンサー

int * ptrならばint * const ptrとして処理されると考えていました。

はい、int * const ptrアドレスがconstです。アドレス変更はできませんが、ポインタが指す先に制約はかかりません。

投稿2020/04/29 07:46

編集2020/04/29 07:51
maisumakun

総合スコア146018

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2020/04/29 07:49

指し先にconst制約のかからないポインタで、constになったaを変更しようとしていますので、動作は未定義です。
aikawa3311

2020/04/29 07:58

なるほど、一見代入できているように見えているコードの挙動は未定義動作だったのですね。回答ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問