今回は、C++での「static」について解説していきます。
「staticって何?」「どんな時に使うの?」と疑問に思ったことはありませんか?
この記事を読み終えると、あなたはstaticの使い方をマスターできると思いますので、ぜひ最後まで読んでいただけると嬉しいです。
staticとは?
staticとは、
・「この変数や関数は特別な扱いをしますよ」
と記憶域期間やスコープを制御するためのキーワード
です。
C++では、staticは使う場所によって意味が変わります。
- 関数内のstatic変数:プログラム終了まで値を保持
- クラスのstaticメンバ:すべてのインスタンスで共有される
- グローバルなstatic変数・関数:そのファイル内でのみ使用可能
それぞれ詳しく見ていきましょう。
関数内のstatic変数
関数内でstatic変数を宣言すると、その変数は関数が終了しても値を保持し続けます。
▼main.cpp
#include <iostream>
void countCall() {
static int count = 0; // 初回のみ実行される
count++;
std::cout << "Called " << count << " times\n";
}
int main() {
countCall();
countCall();
countCall();
return 0;
}実行結果
Called 1 times
Called 2 times
Called 3 times
通常の変数なら毎回0に初期化されますが、static変数は値を保持し続けます。
staticを付けない場合と比較してみましょう。
▼main.cpp
#include <iostream>
void countCallNormal() {
int count = 0; // staticなし
count++;
std::cout << "Called " << count << " times\n";
}
int main() {
countCallNormal();
countCallNormal();
countCallNormal();
return 0;
}実行結果
Called 1 times
Called 1 times
Called 1 times
staticなしでは、毎回0にリセットされてしまいます。
クラスのstaticメンバ変数
クラスでstatic変数を宣言すると、すべてのインスタンスで共有される変数になります。
▼main.cpp
#include <iostream>
class Player {
public:
static int totalPlayers; // static メンバ変数
Player() {
totalPlayers++;
}
};
// static メンバ変数の定義(クラス外で必要)
int Player::totalPlayers = 0;
int main() {
std::cout << "Total: " << Player::totalPlayers << "\n";
Player p1;
std::cout << "Total: " << Player::totalPlayers << "\n";
Player p2;
std::cout << "Total: " << Player::totalPlayers << "\n";
return 0;
}実行結果
Total: 0
Total: 1
Total: 2
staticメンバ変数は、各インスタンスごとではなく、クラス全体で1つだけ存在します。
重要なポイント
- staticメンバ変数はクラス外で定義が必要
クラス名::変数名でアクセスできる- すべてのインスタンスで値を共有する
クラスのstaticメンバ関数
staticメンバ関数は、インスタンスを作らずに呼び出せる関数です。
▼main.cpp
#include <iostream>
class Math {
public:
static int add(int a, int b) {
return a + b;
}
static int multiply(int a, int b) {
return a * b;
}
};
int main() {
// インスタンスを作らずに呼び出せる
std::cout << "3 + 5 = " << Math::add(3, 5) << "\n";
std::cout << "3 * 5 = " << Math::multiply(3, 5) << "\n";
return 0;
}実行結果
3 + 5 = 8
3 * 5 = 15
staticメンバ関数は、非staticメンバ変数にアクセスできないという制限があります。
▼main.cpp
#include <iostream>
class Example {
public:
int normalVar = 10;
static int staticVar;
static void showStatic() {
std::cout << staticVar << "\n"; // OK
// std::cout << normalVar << "\n"; // エラー!
}
};
int Example::staticVar = 20;
int main() {
Example::showStatic();
return 0;
}実行結果
20
staticメンバ関数はインスタンスに紐づかないため、通常のメンバ変数にはアクセスできません。
グローバルなstatic変数・関数
ファイルのグローバルスコープでstaticを使うと、その変数や関数はそのファイル内でのみ使用可能になります。
▼sub.cpp
static int secret = 100; // このファイル内でのみ使える
static void privateFunc() {
// このファイル内でのみ呼び出せる
}▼main.cpp
#include <iostream>
// extern int secret; // エラー!他のファイルのstatic変数は使えない
int main() {
// privateFunc(); // エラー!他のファイルのstatic関数は呼べない
return 0;
}これにより、ファイル内部の実装を隠蔽できます。
モダンC++では、staticの代わりに無名名前空間(namespace)を使う方が推奨されています。
▼sub.cpp
namespace {
int secret = 100; // このファイル内でのみ使える
void privateFunc() {
// このファイル内でのみ呼び出せる
}
}実践的な使い方
staticのよくある使い方を見てみましょう。
シングルトンパターン
staticメンバを使って、クラスのインスタンスを1つだけに制限できます。
▼main.cpp
#include <iostream>
class Singleton {
private:
static Singleton* instance;
Singleton() {} // コンストラクタをprivateに
public:
static Singleton* getInstance() {
if (instance == nullptr) {
instance = new Singleton();
}
return instance;
}
void showMessage() {
std::cout << "Singleton instance\n";
}
};
Singleton* Singleton::instance = nullptr;
int main() {
Singleton* s1 = Singleton::getInstance();
Singleton* s2 = Singleton::getInstance();
s1->showMessage();
// s1とs2は同じインスタンス
std::cout << (s1 == s2 ? "Same instance" : "Different instance");
return 0;
}実行結果
Singleton instance
Same instance
staticを使うべき場面
staticは以下のような場面で使います。
- 関数内static変数:関数の呼び出し回数をカウントしたい時
- クラスのstaticメンバ変数:すべてのインスタンスで共有したいデータがある時
- クラスのstaticメンバ関数:インスタンスなしで呼び出したいユーティリティ関数
- グローバルstatic:ファイル内部の実装を隠蔽したい時(モダンC++では無名名前空間推奨)
まとめ
staticの使い方をまとめます。
- 関数内static変数:値を保持し続ける
- クラスのstaticメンバ変数:すべてのインスタンスで共有される
- クラスのstaticメンバ関数:インスタンスなしで呼び出せる
- グローバルstatic:そのファイル内でのみ使用可能(モダンC++では無名名前空間推奨)
- staticメンバ変数はクラス外で定義が必要
これでstaticの使い方はバッチリですね!
適切な場面でstaticを活用して、より効率的なC++プログラムを書いてみてください。
ここまで読んでくださり、ありがとうございました。
この記事が皆様の学習に役立てば幸いです。


