コンテンツにスキップ

最終更新:2026-10-12

C++ static 静的メンバと生存期間

著者について

個人公式アカウント(WeChat):

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; 
} 

出力:

0 1 2 3 4 

上のプログラムでは、変数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; 
} 

出力:

1

静的メンバ

  • クラスオブジェクトを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"; 
} 

出力:

Inside Constructor
Inside Destructor
End of main

上のプログラムでは、オブジェクトは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"; 
} 

出力:

Inside Constructor
End of main
Inside Destructor

出力の変化がはっきりわかります。今度は、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(); 
} 

出力:

Welcome to Apple!

アクセス範囲の制限 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);
}
g++は上の2つのコードファイルを正常にコンパイルでき、Hello World!を出力します。しかし、source1.cppのmsgにstaticを付けると、undefined reference to 'msg'というコンパイルエラーが発生します:
// source1.cpp
extern void sayHello();
static const char* msg = "Hello World!\n";
int main()
{
    sayHello();
    return 0;
}

関連トピック

コメント