はじめに
C++で変数を宣言する際、int x;
のように型を指定するだけでなく、const
や volatile
といった修飾子を付け加えることができます。これらは、その変数がどのように扱われるべきかをコンパイラとプログラマに伝えるための重要なキーワードです。
const
: その変数が変更不可能な「定数」であることを示す。volatile
: その変数が予期せず変更される可能性があることを示し、コンパイラによる最適化を抑制する。
この記事では、これら2つのcv修飾子の意味と、それぞれの正しい使い方を解説します。
1. const
: 変更不可能性
const
(constantの略) は、一度初期化されたら、その後値が変更されることのない変数(定数)を宣言するために使います。
const
変数
const
を付けて宣言された変数は、再代入しようとするとコンパイルエラーになります。
const int MAX_USERS = 100;
// MAX_USERS = 200; // エラー! const変数は変更できない
const
ポインタと参照
const
はポインタや参照と組み合わせることで、より細かい制御が可能になります。
int value = 10;
// 1. ポインタが指す先の値を変更できない (constへのポインタ)
const int* p1 = &value;
// *p1 = 20; // エラー!
p1 = nullptr; // OK: ポインタ自体は変更可能
// 2. ポインタ自体を変更できない (constポインタ)
int* const p2 = &value;
*p2 = 20; // OK: 指す先の値は変更可能
// p2 = nullptr; // エラー!
// 3. 両方とも変更できない
const int* const p3 = &value;
// 4. const参照
const int& ref = value;
// ref = 20; // エラー! 参照経由での変更はできない
const
メンバ関数
クラスのメンバ関数の後ろにconst
を付けると、その関数がオブジェクトのメンバ変数を変更しないことを約束します。const
オブジェクトからは、const
メンバ関数しか呼び出せません。
class Player {
private:
int hp_ = 100;
public:
// constメンバ関数: メンバ変数を変更しない
int getHp() const {
return hp_;
}
// 非constメンバ関数: メンバ変数を変更する
void takeDamage(int damage) {
hp_ -= damage;
}
};
int main() {
const Player const_player;
const_player.getHp(); // OK
// const_player.takeDamage(10); // エラー! constオブジェクトからは非const関数は呼べない
return 0;
}
2. volatile
: 最適化の抑制
volatile
は、const
とは全く異なる目的で使われます。このキーワードは、「この変数の値は、プログラムのコードからは見えない要因(例: ハードウェア、別のスレッド)によって、いつでも変更される可能性がある」とコンパイラに伝えます。
これにより、コンパイラはその変数へのアクセスに関する最適化を抑制し、コードに書かれた通りのメモリアクセスを保証します。
サンプルコード
// volatile変数の例 (概念的なコード)
// 0x1234番地にあるハードウェアのステータスレジスタを指していると仮定
volatile int* status_register = (int*)0x1234;
// 最適化なし: ループのたびに、必ずメモリから値を読み直す
while (*status_register == 0) {
// 待機
}
解説: もし volatile
がなければ、コンパイラは「ループの中で status_register
の値は変わらない」と判断し、最初の読み込みだけでループを最適化(無限ループ)してしまう可能性があります。volatile
は、そのような最適化を防ぎ、毎回ハードウェアレジスタの値を正直に読みに行くように強制します。
まとめ
今回は、C++のcv修飾子 const
と volatile
について解説しました。
const
: 不変性を保証し、プログラムの安全性を高めるために使う。const
を積極的に使うのが良い習慣。volatile
: 最適化を抑制し、メモリへの直接的なアクセスを保証するために使う。主に組み込みシステムやデバイスドライバ開発など、非常に低レベルな場面で必要になる。
一般的なアプリケーションプログラミングで volatile
が必要になることは稀ですが、const
はプログラムの堅牢性を高めるために日常的に使うべき、非常に重要なキーワードです。