【C++】constとは?|変数・引数・メンバ関数での使い方を初心者向けに解説

C++

今回は、C++でよく出てくる「constとは何か」について解説していきます。

「constって何のために付けるの?」
「引数の const& ってよく見るけど何?」
「関数の後ろに付く const の意味がわからない…」

こんな疑問はありませんか?

const は地味に見えて、バグを未然に防ぎ、コードの意図を伝えるとても大切なキーワードです。使いこなせると、他人(未来の自分)が読んでも安心なコードになります。

この記事を読み終えると、あなたはconstの意味・変数/引数/メンバ関数での使い方・初心者がハマりやすいミスをしっかり理解できると思いますので、ぜひ最後まで読んでいただけると嬉しいです。

constとは?

const とは、「あとから変更できない(読み取り専用)」にするためのキーワードです。付けた値を書き換えようとすると、コンパイルエラーで教えてくれます。

#include <iostream>

int main() {
    const int MAX_HP = 100; // 変更しない値

    std::cout << "最大HP: " << MAX_HP << "n";

    // MAX_HP = 120; // ← これはコンパイルエラーになる
    return 0;
}
最大HP: 100

「絶対に変えたくない値」に const を付けておけば、うっかり書き換えるミスを防げます。定数の作り方は #defineとconstexprの違いの記事も参考になります。

なぜconstが必要?

理由は大きく2つです。1つは意図しない変更を防ぐため。もう1つは「この値は変えません」と読み手に伝えるため。const が付いているだけで、その変数を安心して扱えます。

引数のconst(const参照)

関数の引数でよく見る const T& は、コピーせずに参照で受け取りつつ、中では変更しないという書き方です。大きなオブジェクトを渡すときに速くて安全なので定番です。

#include <iostream>
#include <string>

// コピーしない・変更しない、で受け取る
void PrintName(const std::string& name) {
    std::cout << "名前: " << name << "n";
}

int main() {
    std::string player = "Hero";
    PrintName(player);
    return 0;
}
名前: Hero

参照そのものが不安な方は、参照(&)とポインタの違いの記事を先に読むとスッキリします。

メンバ関数のconst

関数の後ろに付く const は、「このメンバ関数はオブジェクトの中身を変更しません」という約束です。読み取り専用の関数(getterなど)に付けます。

class Player {
public:
    int GetHp() const { // 中身を変えないと約束
        return hp;
    }
private:
    int hp = 100;
};

この const を付けておくと、const なオブジェクトからも呼べるようになります。クラスの基本はクラスとは?の記事で確認できます。

【重要】私が実際にconstで困った体験談

個人開発でマップデータを関数に渡すとき、何気なく std::vector値渡しにしていたら、呼ぶたびに巨大な配列がコピーされて処理がガクッと重くなるという不具合にハマりました。

原因は単純で、引数を const std::vector<int>&(const参照)にしていなかったこと。参照に変えた瞬間にコピーが消えて軽くなりました。「大きいものは const& で受け取る」と体で覚えた出来事でした。

const使用時のよくある失敗例と対処法

①大きな引数をconst参照にし忘れる

体験談のとおり、値渡しは無駄なコピーが起きます。変更しない大きな引数は const T& で受け取りましょう。

②constメンバ関数の中でメンバを変更する

const を付けた関数の中でメンバ変数を書き換えるとエラーになります。変更する関数には const を付けないのが基本です。

③ポインタのconstの位置を間違える

const int*(指す先が定数)と int* const(ポインタ自体が定数)は別物です。迷ったら「constは右にあるものを守る」と覚えると整理しやすいです。

注意点

  • 変更しない値・引数には積極的に const を付ける(const correctness)
  • 大きな引数は const T& で受け取る
  • 読み取り専用のメンバ関数には後ろに const を付ける

まとめ

  • const「変更できない」にするキーワード
  • 変数・引数・メンバ関数のそれぞれで役割がある
  • 大きな引数の const& は速くて安全
  • 付けられる所には積極的に付けると、バグに強いコードになる

const は「守り」のキーワードです。最初は付け忘れがちですが、意識して使うだけでコードの安全性がぐっと上がります。まずは変更しない変数と引数から付けてみてください。

関連記事