Перейти к содержанию

Последнее обновление:2026-10-12

C++ статические члены и время жизни

Об авторе

Официальный аккаунт в WeChat:

wechat

При использовании с разными сущностями ключевое слово static имеет разный смысл. Ключевое слово static можно использовать:

Статические переменные: переменные в функциях, переменные в классах

Статические члены класса: объекты класса и функции в классе

Теперь подробно рассмотрим эти применения static:

Статические переменные

  • Статические переменные в функциях

Когда переменная объявлена как static, память под неё выделяется на всё время жизни программы. Даже при многократных вызовах функции память под статическую переменную выделяется только один раз, а значение переменной из предыдущего вызова передаётся в следующий вызов функции. Это очень полезно в 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, инициализируются только один раз — ведь память под них выделяется в отдельном статическом хранилище, — статические переменные в классе разделяются объектами. Для разных объектов не может существовать нескольких копий одной и той же статической переменной. По этой же причине статические переменные нельзя инициализировать с помощью конструктора.

#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, существуют до конца времени жизни программы.

Рассмотрим программу, в которой объект является нестатическим.

#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++ может нормально скомпилировать эти два файла и напечатать Hello World!, но если добавить static к msg в source1.cpp, возникнет ошибка компиляции undefined reference to 'msg':
// source1.cpp
extern void sayHello();
static const char* msg = "Hello World!\n";
int main()
{
    sayHello();
    return 0;
}

Похожие темы

Комментарии