const: 不変性の保証

変更を防いでバグを減らす。const 正確性は基本中の基本。

const
変更不可を宣言。
constexpr
コンパイル時に評価可能な定数・関数。
mutable
const メンバ関数内でも変更可能な変数。

const

ショーケースの中の展示品

const変数は「ガラスケースに入れられた展示品」です。外から見る(読む)ことはできますが、手で触って形を変える(書き込む)ことはできません。

C++では、変数はデフォルトで「変更可能」です。しかし、プログラムのバグの多くは「変わってはいけないものが変わってしまう」ことで起きます。constを使うことで、コンパイラという警備員に「これは変更禁止!」と監視させることができます。

const Usage
// const 変数
const int MAX_SIZE = 100; // 変更不可
// const ポインタ
const int* ptr1 = &x; // 指す先が const (Read-only)
int* const ptr2 = &x; // ポインタ自体が const (Address fixed)
const int* const ptr3 = &x; // 両方 const
// const メンバ関数
class Circle {
double radius_;
public:
double area() const { // メンバを変更しないと約束
return 3.14 * radius_ * radius_;
}
};
効果
// constなし: コピー発生 (O(n))\n// const参照: コピーなし (O(1))
Bad
// ❌ Bad: const なし
void print(std::string s) { // コピー発生
std::cout << s;
}
Good
// ✅ Good: const 参照
void print(const std::string& s) { // コピーなし、変更不可
std::cout << s;
}

constexpr

`const` は「書き換えない」という約束ですが、実行時に値が決まることもあります。一方、`constexpr` は「コンパイル時に値が決まる」ことを保証します。これにより、実行時の計算コストをゼロにできます。

Compile-Time Constant
// constexpr: コンパイル時定数
constexpr int square(int x) { return x * x; }
// コンパイル時に計算される
constexpr int result = square(5); // 25
// 配列のサイズなどに使える
int arr[result]; // OK
// C++17: constexpr if
template<typename T>
auto process(T value) {
if constexpr (std::is_integral_v<T>) {
return value * 2;
} else {
return value;
}
}
Tip: 可能な限り constexpr を使う。定数はマクロ(#define)ではなく constexpr で定義する。

合格ライン

const 参照を関数引数に使える
constexpr 関数を書ける
const メンバ関数の意味を理解している

参考リンク

演習課題

課題1: const 参照
大きな構造体を引数に取る関数を const& で最適化してください。
課題2: constexpr 関数
フィボナッチ数を返す constexpr 関数を作成してください。

次のステップ