最終更新:2026-10-12
C++ static 静的メンバと生存期間¶
著者について¶
個人公式アカウント(WeChat):

異なる型とともに使われるとき、staticキーワードは異なる意味を持ちます。staticキーワードは次のように使うことができます:
静的変数: 関数の中の変数、クラスの中の変数
静的なクラスのメンバ: クラスオブジェクトとクラスの中の関数
それでは、staticのこれらの使い方を詳しく見ていきましょう:
静的変数
- 関数の中の静的変数
変数がstaticとして宣言されると、領域は**プログラムの生存期間中に割り当てられます**。その関数が何回呼び出されても、静的変数の領域が割り当てられるのは**1回だけ**であり、前の呼び出しでの変数の値が次の関数呼び出しに引き継がれます。これはC / C ++や、以前の関数の状態を保存する必要がある他のあらゆるアプリケーションで非常に役立ちます。
#include <iostream>
#include <string>
using namespace std;
void demo()
{
// static variable
static int count = 0;
cout << count << " ";
// value is updated and
// will be carried to next
// function calls
count++;
}
int main()
{
for (int i=0; i<5; i++)
demo();
return 0;
}
出力:
上のプログラムでは、変数countがstaticとして宣言されているのがわかります。したがって、その値は関数呼び出しをまたいで引き継がれます。関数を呼び出すたびに、変数のカウントが初期化されることはありません。
- クラスの中の静的変数
staticとして宣言された変数は、独立した静的ストレージに領域が割り当てられるため、1回しか初期化されず、それゆえクラスの中の静的変数は**オブジェクト間で共有されます**。異なるオブジェクトのために、同じ静的変数の複数のコピーを持つことはできません。また、この理由から、静的変数はコンストラクタで初期化することができません。
#include<iostream>
using namespace std;
class Apple
{
public:
static int i;
Apple()
{
// Do nothing
};
};
int main()
{
Apple obj1;
Apple obj2;
obj1.i =2;
obj2.i = 3;
// prints value of i
cout << obj1.i<<" "<<obj2.i;
}
上のプログラムでは、複数のオブジェクトのために静的変数iの複数のコピーを作ろうとしているのがわかります。しかし、そうはなりませんでした。したがって、クラスの中の静的変数は、次のように、ユーザーがクラスの外でクラス名とスコープ解決演算子を使って明示的に初期化するべきです:
#include<iostream>
using namespace std;
class Apple
{
public:
static int i;
Apple()
{
// Do nothing
};
};
int Apple::i = 1;
int main()
{
Apple obj;
// prints value of i
cout << obj.i;
}
出力:
静的メンバ
- クラスオブジェクトをstaticにする
変数と同じように、オブジェクトもstaticとして宣言されると、プログラムの生存期間までスコープを持ちます。
オブジェクトが非静的である次のプログラムを考えてみましょう。
#include<iostream>
using namespace std;
class Apple
{
int i;
public:
Apple()
{
i = 0;
cout << "Inside Constructor\n";
}
~Apple()
{
cout << "Inside Destructor\n";
}
};
int main()
{
int x = 0;
if (x==0)
{
Apple obj;
}
cout << "End of main\n";
}
出力:
上のプログラムでは、オブジェクトはifブロックの中で非静的として宣言されています。したがって、変数のスコープはifブロックの中だけです。そのため、オブジェクトが作られるときにコンストラクタが呼び出され、ifブロックの制御が抜けるときに同時にデストラクタが呼び出されます。なぜならオブジェクトのスコープは、それが宣言されたifブロックの中だけだからです。 オブジェクトを静的に宣言すると、出力がどのように変化するか見てみましょう。
#include<iostream>
using namespace std;
class Apple
{
int i;
public:
Apple()
{
i = 0;
cout << "Inside Constructor\n";
}
~Apple()
{
cout << "Inside Destructor\n";
}
};
int main()
{
int x = 0;
if (x==0)
{
static Apple obj;
}
cout << "End of main\n";
}
出力:
出力の変化がはっきりわかります。今度は、mainが終わった後にデストラクタが呼び出されます。これは、静的オブジェクトのスコープがプログラムの生存期間を通じて続くためです。
- クラスの中の静的関数
クラスの中の静的データメンバや静的変数と同じように、静的メンバ関数もクラスのオブジェクトに依存しません。静的メンバ関数を呼び出すのに、オブジェクトと'.'を使うことは許されています。しかし、クラス名とスコープ解決演算子を使って静的メンバを呼び出すことが推奨されます。
静的メンバ関数がアクセスできるのは静的データメンバか他の静的メンバ関数だけであり、クラスの非静的データメンバやメンバ関数にはアクセスできません。
#include<iostream>
using namespace std;
class Apple
{
public:
// static member function
static void printMsg()
{
cout<<"Welcome to Apple!";
}
};
// main function
int main()
{
// invoking a static member function
Apple::printMsg();
}
出力:
アクセス範囲の制限 staticにはアクセス範囲を制限する役割もあります(匿名名前空間に似ています)。issueより:https://github.com/Light-City/CPlusPlusThings/issues/142
// source1.cpp
extern void sayHello();
const char* msg = "Hello World!\n";
int main()
{
sayHello();
return 0;
}
// source2.cpp
#include <cstdio>
extern char* msg;
void sayHello()
{
printf("%s", msg);
}
// source1.cpp
extern void sayHello();
static const char* msg = "Hello World!\n";
int main()
{
sayHello();
return 0;
}
関連トピック¶
- C++ 純粋仮想関数と抽象クラス | C++那些事
- C++ assert アサーション | C++那些事
- C++ ビットフィールド | C++那些事
- C 言語による C++ 多態の実現 | C++那些事
- C++ const 定数と修飾 | C++那些事
- C++ const ファミリー | C++那些事
- C++ 間接参照演算子 * | C++那些事
- C++ 初期化と代入 | C++那些事
- C++ 複数戻り値の書き方 | C++那些事
- C++ mutable キーワード | C++那些事