なまもの備忘録

気になったことをつらつらと書いていきます

C++のconst指定子とポインタのややこしい話

C++でよく変更する予定のない変数の型の前にconstを付けるが、あれは唯の目印のようなものではなく、const ホニャララという新しい型を宣言している感覚に近いっぽい。
このconstの仕様はC言語時代からの負の遺産で大分ややこしいものになっているため、ここに少し整理しておくことにする。
double型を例にとって整理しよう。

double x;//一般的なdouble型の宣言
double* x;//double型のポインタの宣言
const double x;//double型で、xの値を変更することはできない
const double* x;//値を変更することのできないdouble型(const double)へのポインタ
double const* x;//実はこれは上と同じものを指す。この辺からややこしい。
double* const x;//xはdouble型のポインタで、ポインタの指す先をかえることはできない。ポインタが指しているdouble型の変数に別の値を代入することはできる。
const double* const x;//変更不能なポインタが指しているのはconst double型なので、こちらに別の値を代入することもできない。
double const* const x;//上と同じ
const double* const* const* x;//const double型へのポインタも変更不能で、そのポインタへのポインタも変更不能だが、このポインタへのポインタにはconst指定子がついていないので変更できる。
deouble const* const* const* x;//上と同じ

おわかり頂けただろうか?
他に、f(const double x)のような関数にdouble型の変数を代入しても問題ないが、f(double x)のような関数にconst double型の変数を代入するとコンパイルエラーになる。
また、この話には直接関係がないが、関数ポインタへのアドレス参照演算子は無視される、intなどの型とintなどのリストは内部では違う型として扱われているので、int型のポインタのポインタにint型のリストのアドレスを代入しようとしてもエラーを吐くなどの話を今日しったのでメモしておく。