C++において、constは重要なキーワードの一つです。
しかし、初心者にとってはその意味や使い方がわかりづらいこともあります。
本記事では、C++のconstについて詳しく解説し、サンプルコードを交えてわかりやすく解説します。
constとは何か
C++におけるconstは、変数や関数の引数、戻り値などを定数として扱うためのキーワードです。つまり、一度値が代入されたらその後変更できないようにすることができます。
例えば、以下のようにint型の変数を宣言し、constキーワードを付けることで定数として扱うことができます。
const int num = 10;
この場合、numに対して再代入を行おうとするとコンパイルエラーが発生します。
また、関数の引数や戻り値にもconstキーワードを使用することができます。これによって、関数内部で引数や戻り値の値を変更することを禁止して、意図しない代入によるバグを予防することができます。
void func(const int arg) {
// argに対して再代入しようとするとコンパイルエラーが発生する
}
const int func2() {
return 10;
}
以上がconstキーワードの基本的な使い方です。次は具体的な利用方法について解説します。
constの使い方
C++におけるconstは、変数や関数、ポインタなどに対して使用することができます。ここでは、それぞれの使い方について詳しく解説します。
変数の宣言時にconstを使う
変数を宣言する際に、その変数が値を変更されないようにしたい場合は、constキーワードを使用します。以下は、int型の定数を宣言する例です。
const int num = 10;
このように定義された変数は、後から値を変更することができません。
関数の引数にconstを使う
関数の引数にconstキーワードを付けることで、その引数が関数内で値を変更されないようにすることができます。以下は、int型の引数を取り、その値を2倍した結果を返す関数です。
int double_num(const int num) {
return num * 2;
}
このように定義された関数では、numの値が関数内で変更されることはありません。
関数の戻り値にconstを使う
関数の戻り値にconstキーワードを付けることで、その戻り値が呼び出し元で値を変更されないようにすることができます。以下は、int型の定数を返す関数です。
const int get_num() {
return 10;
}
const int result = get_num();
result += 5; //コンパイルエラー
このように定義された関数では、get_num()から返される値は呼び出し元で変更することができません。
constメンバ関数
クラス内部で定義されたメンバ関数でも、引数や戻り値同様にconstキーワードを使用することができます。
constキーワードがついたメンバ関数は、「オブジェクト自身」もしくは「オブジェクト自身から参照・ポインタ経由で呼ばれた場合」しか呼び出すことが出来ません。
また、mutable修飾子がついていない変数への代入を行うこともできないため、constキーワードがついたメンバ関数内では変数の値の変更が行われないということも伝えることができます。
class MyClass {
public:
void func() const {
// オブジェクト自身やそのメンバー変数等読み込み専用処理
}
};
constポインタ
ポインタ自体もconst指定子(*) をつける事が可能です。
これらのポインタでは指し示すアドレス の書き換え禁止です。ただしアドレスが指す先のデータ自体は書き換え可能です。 以下は例です。
int num = 10;
int* const ptr = # // ポインタptr自体へ代入不可だが、numへ代入可能
*ptr = 20; // ポインタが指すnumへの代入なのでOK
// ptr = &another_num; // ポインタのアドレスの書き換えはでいないためコンパイルエラー
構文が型名* const 変数名
となっている点に注意してください。const 型名* 変数名
にすると、ポインタにアドレスを再代入して参照先を変更できますが、値の変更ができなくなります。
const参照
参照もまた、参照先データ(オブジェクト) の書き換え禁止指定子(&) をつける事も可能です。 以下は例です。
int num = 10;
const int& ref1 = num; // 参照ref1経由ではnum書き換え不可
// ref1++; // NG: 参照先データ(num) 書き換え不可
num++; // OK: 参照(ref1) 経由しなくてもOK
cout << "ref1=" << ref1 << endl; // OK: ref1=11