「どうせ変更しないし、別に const 付けなくてよくない?」
C++の const。存在は知っているけど、「わざわざ付けるの面倒くさい」「コンパイラが何とかしてくれるでしょ」と思って、ほとんど使っていませんでした。
そんな私のコードは、こんな感じでした。
void processOrder(Order order, std::vector<Item>& items) {
int total = 0;
for (int i = 0; i < items.size(); ++i) {
total += items[i].price;
items[i].processed = true; // ← あれ?ここで items を変更してる…意図的?
}
order.total = total; // ← order はコピーだから元のオブジェクトは変わらない…バグ?
}
このコードのバグが分かりますか?
-
itemsを参照渡し(&)で受け取っている=関数内での変更が呼び出し元に影響する。processed = trueは意図的なのか、うっかり触ってしまったのか、コードから判断できない。 -
orderは値渡し(コピー)なので、order.total = totalとしても呼び出し元のOrderは変わらない。これは100%バグ。
constを習慣的に付けていれば、このバグはコンパイル時に即座に検出されていたのです。
const は「俺はこれを変えるつもりはない」という宣言書
引数の const :「触らない」契約
// 改善版:意図が明確になる
void processOrder(Order& order, const std::vector<Item>& items) {
// ↑ 変更する ↑ 変更しない(const参照)
int total = 0;
for (int i = 0; i < items.size(); ++i) {
total += items[i].price;
items[i].processed = true; // ❌ コンパイルエラー!constなので変更できない
}
order.total = total; // ✅ order は非constなので変更OK
}
items に const を付けた瞬間、「items[i].processed = true」の行でコンパイルエラーが発生します。もしこの変更が意図的なら const を外せばいいし、うっかりミスなら実行前にバグが見つかるのです。
変数の const:意図しない再代入を防ぐ
const int maxRetries = 3;
// ... 200行のコード ...
maxRetries = 5; // ❌ コンパイルエラー!constは再代入できない
「この値は最初に決めたら変わらないはずだ」というものには、全て const を付けます。後から誰かが(未来の自分を含む)うっかり書き換えてしまうことを、コンパイラが防いでくれます。
メンバ関数の const:オブジェクトの状態を変えない約束
class Account {
int balance;
public:
int getBalance() const { return balance; } // ← オブジェクトを変更しないことを保証
void withdraw(int amount) { balance -= amount; }
};
const メンバ関数の中で this->balance を変更しようとすると、コンパイルエラーになります。「このメソッドはオブジェクトの状態を一切変えません」という、コンパイラが強制する契約です。
const をデフォルトにする思考法
モダンC++のベストプラクティスは**「まず const を付ける。変更する必要がある場合だけ外す」**です(const by default)。
✅ const を付けることで得られるもの:
- コンパイル時のバグ検出(意図しない変更がエラーになる)
- コードの可読性向上(「この変数は変わらない」が一目で分かる)
- コンパイラの最適化ヒント(const な変数は最適化しやすい)
- スレッドセーフ性の向上(const なデータは競合しない)
❌ const を付けないことで得られるもの:
- タイプ数が5文字減る
5文字の手間を惜しんでバグを生むか、5文字の投資でコンパイラを味方につけるか。const は「面倒な修飾子」ではなく、C++における最もコスパの高い品質保証ツールです。