# ptr* get() const { return ptr_; } に意味はあるのか? ## 関数とconst そもそも関数に対してconstをつけるとどうなるのか? ```cpp= // オブジェクトのメンバを書き換えない State get() const { return state_; } // 書き換えるのでconstはつけられない void set_state(State state) { state_ = state; } // これはコンパイルエラー: // bool set_state(State state) const { state_ = state; } // この関数自体は書き換えていないように見えるが、constではない関数を呼ぶのでアウト bool MaybeSetState(State state) { if (state_ == state) { return; } set_state(state); } ``` constをつけておくことで、その関数が自身を書き換えないことを保証している。 なおstaticな関数やクラスのメンバでない関数にはconstをつけても意味がないしコンパイルエラーになる。 ### mutable C++には[mutable](https://en.cppreference.com/w/cpp/language/cv)というキーワードもあり、これをつけるとconstの中でも変更することができる。 ```cpp= // コンパイルOK void set_state(State state) const { state_ = state; } mutable State state_; ``` これは例えばログ用のキャッシュなどに使うと良い。 ## 返り値がポインタの場合 さて、constを関数につけるとき、オブジェクトの値を変えないでほしい気がする。返り値がポインタの場合普通に変えられてしまう。 ```cpp= ptr* get() const { return ptr_; } // get() 自体は値を変えないが… auto* p = get(); // それで返したポインタを使って値を変えられてしまう p->set_state(state); ``` これを防ぐためにはどうしたらいい? 返り値のポインタにもconstを書いておこう。 ```cpp= const ptr* get() const { return ptr_; } // get() 自体は値を変えないし auto* p = get(); // それで返したポインタに対してconstでない関数を呼ぼうとするとコンパイルエラー // p->set_state(state); ``` ### なぜこうなる? C++的には、オブジェクトに直にぶら下がってるメンバの値が変わらなければセーフ。 なので、`ptr_`自体の値が変えられるならダメで、`get() const`はそれを守っている。 逆にメンバのメンバは管轄外というデザインになっている。 ## 結論 意味あった。