static 在 C++ 中的各种用法

以下是 static 的主要用法,包括静态变量、静态全局变量、静态局部变量、静态函数、静态成员函数和静态成员变量的详细说明。

#include <iostream>
#include <string>

// 1. 静态全局变量(文件作用域)
static int globalCount = 0; // 仅当前文件可见

// 2. 普通全局变量(对比)
int nonStaticGlobal = 0; // 其他文件可通过 extern 访问

// 3. 静态函数(文件作用域)
static void incrementGlobalCount() {
    globalCount++;
    std::cout << "Static globalCount: " << globalCount << "\n";
}

class MyClass
{
private:
    // 4. 静态成员变量
    static int staticMemberCount; // 共享于所有对象
    int instanceCount;

public:
    MyClass(int count) : instanceCount(count)
    {
        staticMemberCount++;
    }
    // 5. 静态成员函数
    static int getStaticMemberCount() 
    {
        return staticMemberCount; // 只能访问静态成员
    }

    int getInstanceCount() const {
    return instanceCount;
}

// 6. 静态局部变量(示例)
    void demonstrateStaticLocal()
    {
        static int localStaticVar = 0; // 仅初始化一次,保留值
        localStaticVar++;
        std::cout << "Static local variable: " << localStaticVar << "\n";
    }
};

// 静态成员变量的定义(必须在类外定义)
int MyClass::staticMemberCount = 0;

    int main() 
{
    // 测试静态全局变量
    incrementGlobalCount(); // 输出 1
    incrementGlobalCount(); // 输出 2
    // 测试静态成员变量和静态成员函数
    MyClass obj1(10);
    MyClass obj2(20);
    std::cout << "Static member count: " << MyClass::getStaticMemberCount() << "\n"; // 输出 2
    std::cout << "Instance count obj1: " << obj1.getInstanceCount() << "\n"; // 输出 10
    std::cout << "Instance count obj2: " << obj2.getInstanceCount() << "\n"; // 输出 20

    // 测试静态局部变量
    obj1.demonstrateStaticLocal(); // 输出 1
    obj2.demonstrateStaticLocal(); // 输出 2

    return 0;
}

1. 静态全局变量

  • 定义:在文件作用域中声明的全局变量,前面加 static
  • 作用
    • 限制变量的链接性为内部链接(internal linkage),仅在当前翻译单元(源文件)可见。
    • 其他源文件无法通过 extern 访问。
  • 特点
    • 初始化只发生一次,生命周期为整个程序运行期间。
    • 默认初始化为 0(如果未显式初始化)。
  • 示例
    1
    static int globalCount = 0; // 仅当前文件可见
    • 对比普通全局变量:
      1
      int nonStaticGlobal = 0; // 可被其他文件通过 extern 访问

2. 静态局部变量

  • 定义:在函数或块作用域内声明的变量,前面加 static
  • 作用
    • 变量只初始化一次,之后保留其值。
    • 生命周期为整个程序运行期间,但作用域仅限于声明的块。
  • 特点
    • 默认初始化为 0(如果未显式初始化)。
    • C++11 及以后,静态局部变量的初始化是线程安全的
  • 示例
    1
    2
    3
    4
    5
    void demonstrateStaticLocal() {
    static int localStaticVar = 0; // 仅初始化一次
    localStaticVar++;
    std::cout << localStaticVar << "\n"; // 每次调用递增
    }
    • 调用两次,输出 12

3. 静态函数

  • 定义:在文件作用域中声明的函数,前面加 static
  • 作用
    • 限制函数的链接性为内部链接,仅在当前翻译单元可见。
    • 防止其他源文件通过 extern 调用。
  • 特点
    • 用于封装文件内部的辅助函数,类似于静态全局变量的限制。
  • 示例
    1
    2
    3
    4
    static void incrementGlobalCount() {
    globalCount++;
    std::cout << "Static globalCount: " << globalCount << "\n";
    }

4. 静态成员变量

  • 定义:在类中声明的成员变量,前面加 static
  • 作用
    • 所有类对象共享同一份静态成员变量。
    • 不属于某个具体对象,而是属于类本身。
  • 特点
    • 必须在类外定义并初始化(通常在源文件中)。
    • 生命周期为整个程序运行期间。
    • 可通过类名直接访问(如 MyClass::staticMemberCount)。
  • 示例
    1
    2
    3
    4
    5
    class MyClass {
    private:
    static int staticMemberCount; // 声明
    };
    int MyClass::staticMemberCount = 0; // 定义并初始化

5. 静态成员函数

  • 定义:在类中声明的成员函数,前面加 static

  • 作用

    • 不依赖于类的具体对象,只能访问类的静态成员(变量或函数),无法访问非静态成员函数和成员。
    • 可通过类名直接调用(如 MyClass::getStaticMemberCount())。
  • 特点

    • 没有隐式的 this 指针,因为不绑定到任何对象。
    • 常用于访问或操作静态成员变量。
  • 示例

    1
    2
    3
    4
    5
    6
    class MyClass {
    public:
    static int getStaticMemberCount() {
    return staticMemberCount; // 访问静态成员
    }
    };

6. 注意事项与总结

  • 生命周期与作用域
    • 所有 static 变量(全局、局部、成员)的生命周期都是程序运行期间。
    • 作用域取决于声明位置(文件、函数、类)。
  • 线程安全
    • 静态局部变量在 C++11 及以后初始化是线程安全的。
    • 静态全局变量和静态成员变量的访问需开发者自行确保线程安全。
  • 内存管理
    • 静态变量存储在数据段(.data.bss),非堆或栈。
    • 无需手动释放,程序结束时由系统自动回收。
  • 与上下文的联系
    • 静态局部变量的线程安全特性在单例模式(如 Meyers’ Singleton)中非常有用
    • 静态成员变量类似于饿汉式单例的预加载机制(程序启动时初始化)。