const (C/C++)
読み:コンスト
外語:const

 C/C++予約語の一つで、いくつかの意味を持ち、主に変数に使う場合とクラスのメンバー関数に使う場合とがある。
目次

概要
 当初のCにはなく、ANSI Cから追加された。C++には最初からある。
 C/C++では「上書き不可」とし、その変数を読み込み専用の定数として扱えるようにする機能を提供する。
 ただし、ポインター型に対してconstを使うと、使い方によって挙動が変化するので注意が必要である。

変数

型定義

使い方
 変数の型定義に使うconstの書き方には、二種類の使い方から三通りの組み合わせがある。
  1. hoge(const char *src)
  2. hoge(char * const src)
  3. hoge(const char * const src)
 以下、順に説明する。

hoge(const char *src)
 一般的に使われるのが、このhoge(const char *src)という書き方である。
 なお、hoge(char const *src)と書いても同じ意味である。
 この時、読み出し専用になるのはsrcではなく、srcが指し示す先にあるもの、である。従って、この関数内でsrcに代入してもエラーにならないが、*src=0;などとすればエラーになる。

hoge(char * const src)
 一方、srcそのものを読み出し専用にするにはhoge(char * const src)と書くことになる。
 srcに代入すればエラーになるが、srcが指し示す先にあるものは保護されない。

hoge(const char * const src)
 そしてsrcとsrcが指し示す先にあるものの双方を読み出し専用にしたければ、hoge(const char * const src)などと書くことになる。
 ただし、一般的な利用法としては、最初の例にあるような、引数ポインターである場合に、そのポインターの示す先にあるものを読み出し専用にする用途で用いられることが多い。

#defineの代わり
 Cでは、定数の定義に#defineが使われた。C++でも使われるが、C++ではそれより、constを使う方が良い。
 #define BUFSIZE 1000
 #defineの場合「型」が定かでない。C++は型にうるさい言語であるため、定数であっても型を持つことが望ましい。
 const size_t BUFSIZE=1000;
 constで定義したBUFSIZEは、#defineで定義したBUFSIZEとは違って変数である。

関数

関数概要
 変数に使うconstの書き方には、三種類の使い方がある。
  1. const int &hoge() { ... };
  2. const Hoge hoge() { ... };
  3. int hoge() const { ... };

参照返却値のconst
 関数自体に対するconstは、その返却値が読み出し専用であることを表わす。
 具体的には、次のように定義される関数である。
 const 任意の型 &func();
 この場合、返却値が参照の場合、参照を得ても左辺値になることが出来ない。
 例えば、参照を返すメンバー関数hogeがあったとして、次のように定義されているとする。
 int i;
 const int &hoge() { return i; }
 この場合、func.hoge()で参照を得ても、左辺値に出来ない。
 func.hoge() = 0; // 不可
 左辺値にすると、コンパイルエラーが発生する。

敢えてconstを返却する
 参照に限らず、constのも返すことができる。そうすると、以下のような利点が考えられる。
 class Hoge {
 public:
 ...
 // 敢えてconstの値を返す
 const Hoge operator+(const Hoge &rhs) const { return ...; }
 };
 ここで次のような(誤った)使い方をするとエラーとなる。
 Hoge a, b, c;
 ...
 if (a + b = c) {
 ...
 }
 本来は「a + b == c」のつもりだったが、誤って=と書いてしまった例である。しかし、constのおかげでコンパイルエラーとなり、バグの混入を避けることができた。
 バグの混入を減らすために、積極的にconstを付けるべきである。スコット・メイヤーズ(著)小林 健一郎(訳)のC++基本書「Effective C++ 原著第3版」にも「第3項 可能ならいつでもconstを使おう」という記述がある。

メンバー関数のconst
 クラスのメンバー関数に用いた場合、そのメソッドインスタンスの内容を変更しないことを宣言する。
 この宣言をする場合は、引数リストの後にconstを記述する。プロトタイプ宣言の記述も同様である。
 int hoge() const { ... };
 constで定義された関数内でメンバー変数の変更をすると、コンパイルエラーが発生する。但し、mutableで修飾したメンバー変数だけは、constであっても例外的に書き換えができる。
 また、constなインスタンスからはconstなしのメンバー関数を呼ぶことはできない。

再検索