C++ 中 static 关键字

一、C++的static 的 5 种主要用法

// 1. 静态局部变量(函数执行完后不被销毁,保持其值)

// 2. 静态全局变量(限制作用域在当前文件)

// 3. 静态成员变量(属于类而不是对象,所有对象共享)

// 4. 静态成员函数(属于类而不是对象,不能访问非静态成员)

// 5. 静态断言 (static_assert)

总结对比

特性 静态局部变量1 静态全局变量2 静态成员变量3 静态成员函数4
作用域 函数内部 文件内部 类作用域 类作用域
生命周期 程序运行期 程序运行期 程序运行期 程序运行期
内存位置 数据段 数据段 数据段 代码段
初始化 第一次执行时 main()前 main()前 N/A
线程安全 C++11后是

最佳实践:

  1. 使用静态局部变量1实现单例模式

  2. 使用静态成员函数4作为工具函数

  3. 使用静态成员变量3记录类级别信息

  4. 避免过度使用静态变量(破坏封装性)

  5. 多线程环境下注意同步问题

二、静态局部变量1

特点: 函数执行完后不被销毁,保持其值

cpp 复制代码
#include <iostream>
using namespace std;

void demo_static_local() {
    cout << "\n=== 静态局部变量 ===" << endl;
    
    // 普通局部变量
    auto normal_counter = []() {
        int count = 0;  // 每次调用都重新初始化
        count++;
        return count;
    };
    
    // 静态局部变量
    auto static_counter = []() {
        static int count = 0;  // 只初始化一次
        count++;
        return count;
    };
    
    cout << "普通局部变量: ";
    for (int i = 0; i < 5; i++) {
        cout << normal_counter() << " ";  // 输出: 1 1 1 1 1
    }
    
    cout << "\n静态局部变量: ";
    for (int i = 0; i < 5; i++) {
        cout << static_counter() << " ";  // 输出: 1 2 3 4 5
    }
    cout << endl;
}

// 实际应用场景
class Singleton {
private:
    Singleton() { cout << "Singleton created" << endl; }
    
public:
    static Singleton& getInstance() {
        static Singleton instance;  // 线程安全(C++11),只创建一次
        return instance;
    }
    
    void show() { cout << "Singleton instance" << endl; }
};

void test_singleton() {
    auto& s1 = Singleton::getInstance();
    auto& s2 = Singleton::getInstance();
    
    cout << "两次获取的是同一个实例吗?" 
         << (&s1 == &s2 ? "是" : "否") << endl;
}

三、静态全局变量2

特点: 限制作用域在当前文件

cpp 复制代码
// file1.cpp
#include <iostream>

int global_var = 100;           // 全局变量,其他文件可见
static int static_global = 200; // 静态全局,仅当前文件可见

void show_globals() {
    std::cout << "global_var: " << global_var << std::endl;
    std::cout << "static_global: " << static_global << std::endl;
    
    static_global++;  // 可以修改
}

// file2.cpp
extern int global_var;  // 正确,可以访问
// extern int static_global;  // 错误!链接器找不到

四、静态成员变量3(类变量)

特点: 属于类而不是对象,所有对象共享

cpp 复制代码
#include <iostream>
using namespace std;

class Student {
private:
    string name;
    int id;
    
public:
    // 静态成员变量声明(必须在类外定义)
    static int totalStudents;
    static const int MAX_CLASS_SIZE = 50;  // 静态常量可以在类内初始化
    
    Student(string n) : name(n) {
        id = ++totalStudents;  // 使用静态变量
        cout << "创建学生: " << name << " (ID: " << id << ")" << endl;
    }
    
    ~Student() {
        totalStudents--;
        cout << "删除学生: " << name << endl;
    }
    
    void show() const {
        cout << name << " (ID: " << id << "), 总人数: " 
             << totalStudents << "/" << MAX_CLASS_SIZE << endl;
    }
    
    // 静态成员函数可以访问静态成员,不能访问非静态成员
    static int getTotal() { return totalStudents; }
    static bool isClassFull() { return totalStudents >= MAX_CLASS_SIZE; }
};

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

void demo_static_member() {
    cout << "\n=== 静态成员变量 ===" << endl;
    
    // 通过类名访问静态成员
    cout << "初始总人数: " << Student::getTotal() << endl;
    cout << "班级已满?" << (Student::isClassFull() ? "是" : "否") << endl;
    
    // 创建学生
    Student s1("张三");
    Student s2("李四");
    Student s3("王五");
    
    // 通过对象访问静态成员
    s1.show();
    s2.show();
    s3.show();
    
    // 通过类名访问
    cout << "当前总人数: " << Student::getTotal() << endl;
    
    // 删除对象
    {
        Student s4("赵六");
        cout << "临时学生加入后总人数: " << Student::getTotal() << endl;
    }  // s4 离开作用域,自动销毁
    
    cout << "临时学生离开后总人数: " << Student::getTotal() << endl;
}

五、静态成员函数4

特点: 属于类而不是对象,不能访问非静态成员

cpp 复制代码
class MathUtils {
private:
    MathUtils() {}  // 私有构造函数,防止实例化
    
public:
    // 静态成员函数 - 工具函数
    static double add(double a, double b) { return a + b; }
    static double multiply(double a, double b) { return a * b; }
    
    static double circleArea(double radius) {
        return PI * radius * radius;
    }
    
    static double power(double base, int exponent) {
        double result = 1.0;
        for (int i = 0; i < exponent; i++) {
            result *= base;
        }
        return result;
    }
    
    // 静态常量
    static constexpr double PI = 3.141592653589793;
};

class Configuration {
private:
    static string appName;
    static string version;
    static bool debugMode;
    
public:
    // 静态getter/setter
    static string getAppName() { return appName; }
    static void setAppName(const string& name) { appName = name; }
    
    static string getVersion() { return version; }
    static bool isDebugMode() { return debugMode; }
    static void setDebugMode(bool mode) { debugMode = mode; }
    
    // 静态初始化函数
    static void initialize() {
        appName = "MyApp";
        version = "1.0.0";
        debugMode = false;
        cout << "配置初始化完成" << endl;
    }
    
    static void showConfig() {
        cout << "应用名称: " << appName << endl;
        cout << "版本: " << version << endl;
        cout << "调试模式: " << (debugMode ? "开启" : "关闭") << endl;
    }
};

// 静态成员定义
string Configuration::appName;
string Configuration::version;
bool Configuration::debugMode;

void demo_static_functions() {
    cout << "\n=== 静态成员函数 ===" << endl;
    
    // 使用工具类
    cout << "MathUtils 示例:" << endl;
    cout << "5 + 3 = " << MathUtils::add(5, 3) << endl;
    cout << "5 * 3 = " << MathUtils::multiply(5, 3) << endl;
    cout << "半径为2的圆面积: " << MathUtils::circleArea(2) << endl;
    cout << "2^5 = " << MathUtils::power(2, 5) << endl;
    
    // 使用配置类
    cout << "\nConfiguration 示例:" << endl;
    Configuration::initialize();
    Configuration::showConfig();
    
    // 修改配置
    Configuration::setAppName("SuperApp");
    Configuration::setDebugMode(true);
    cout << "\n修改后的配置:" << endl;
    Configuration::showConfig();
}

六、静态断言5(static_assert)

cpp 复制代码
// 编译时检查
template<typename T>
class Vector {
    static_assert(sizeof(T) <= 16, "T 类型太大,不适合Vector");
    
public:
    // 类定义...
};

// 平台检查
static_assert(sizeof(void*) == 8, "需要64位系统");

// 常量表达式检查
constexpr int MAX_SIZE = 100;
static_assert(MAX_SIZE > 0, "MAX_SIZE 必须大于0");

void demo_static_assert() {
    cout << "\n=== 静态断言 ===" << endl;
    
    // static_assert 在编译时检查
    static_assert(sizeof(int) == 4, "int 必须是4字节");
    static_assert(sizeof(char) == 1, "char 必须是1字节");
    
    cout << "静态断言检查通过" << endl;
}

七、static 在模板中的应用

cpp 复制代码
template<typename T>
class TypeTracker {
private:
    static int count;  // 每个模板实例都有自己的静态变量
    
public:
    TypeTracker() { count++; }
    ~TypeTracker() { count--; }
    
    static int getCount() { return count; }
};

// 每个模板实例化都需要单独定义静态成员
template<typename T>
int TypeTracker<T>::count = 0;

void demo_template_static() {
    cout << "\n=== 模板中的静态成员 ===" << endl;
    
    TypeTracker<int> t1, t2, t3;
    TypeTracker<double> d1, d2;
    TypeTracker<string> s1;
    
    cout << "TypeTracker<int> 实例数: " 
         << TypeTracker<int>::getCount() << endl;
    cout << "TypeTracker<double> 实例数: " 
         << TypeTracker<double>::getCount() << endl;
    cout << "TypeTracker<string> 实例数: " 
         << TypeTracker<string>::getCount() << endl;
}

八、完整代码示例

cpp 复制代码
//数据库连接池
#include <iostream>
#include <vector>
#include <string>
#include <memory>
using namespace std;

class DatabaseConnection {
private:
    string connectionId;
    
public:
    DatabaseConnection(string id) : connectionId(id) {
        cout << "创建连接: " << connectionId << endl;
    }
    
    ~DatabaseConnection() {
        cout << "关闭连接: " << connectionId << endl;
    }
    
    void query(const string& sql) {
        cout << "[" << connectionId << "] 执行查询: " << sql << endl;
    }
};

class ConnectionPool {
private:
    static const int MAX_POOL_SIZE = 5;
    static vector<shared_ptr<DatabaseConnection>> pool;
    static int createdCount;
    
    // 私有构造函数,防止实例化
    ConnectionPool() = delete;
    
public:
    static shared_ptr<DatabaseConnection> getConnection() {
        // 如果池中有可用连接
        for (auto& conn : pool) {
            if (conn.use_count() == 1) {  // 只有池子持有引用
                cout << "从连接池获取现有连接" << endl;
                return conn;
            }
        }
        
        // 创建新连接(如果不超过最大限制)
        if (createdCount < MAX_POOL_SIZE) {
            string id = "DB_CONN_" + to_string(createdCount + 1);
            auto conn = make_shared<DatabaseConnection>(id);
            pool.push_back(conn);
            createdCount++;
            cout << "创建新连接加入池中" << endl;
            return conn;
        }
        
        throw runtime_error("连接池已满,无法创建新连接");
    }
    
    static void showPoolStatus() {
        cout << "\n=== 连接池状态 ===" << endl;
        cout << "已创建连接数: " << createdCount << endl;
        cout << "池中连接数: " << pool.size() << endl;
        
        int available = 0;
        for (size_t i = 0; i < pool.size(); i++) {
            cout << "连接 " << i+1 << ": ";
            if (pool[i].use_count() == 1) {
                cout << "可用" << endl;
                available++;
            } else {
                cout << "正在使用" << endl;
            }
        }
        cout << "可用连接: " << available << endl;
    }
};

// 静态成员定义
vector<shared_ptr<DatabaseConnection>> ConnectionPool::pool;
int ConnectionPool::createdCount = 0;

void demo_connection_pool() {
    cout << "\n=== 数据库连接池示例 ===" << endl;
    
    try {
        // 获取连接
        auto conn1 = ConnectionPool::getConnection();
        auto conn2 = ConnectionPool::getConnection();
        
        // 使用连接
        conn1->query("SELECT * FROM users");
        conn2->query("UPDATE products SET price = 100");
        
        ConnectionPool::showPoolStatus();
        
        // 获取更多连接
        auto conn3 = ConnectionPool::getConnection();
        auto conn4 = ConnectionPool::getConnection();
        auto conn5 = ConnectionPool::getConnection();
        
        ConnectionPool::showPoolStatus();
        
        // 尝试获取第6个连接(应该失败)
        try {
            auto conn6 = ConnectionPool::getConnection();
        } catch (const exception& e) {
            cout << "错误: " << e.what() << endl;
        }
        
        // 释放连接
        cout << "\n释放一些连接..." << endl;
        conn1.reset();
        conn2.reset();
        
        ConnectionPool::showPoolStatus();
        
        // 现在应该可以获取连接了
        auto conn6 = ConnectionPool::getConnection();
        cout << "成功获取新连接" << endl;
        
    } catch (const exception& e) {
        cout << "异常: " << e.what() << endl;
    }
}

九、static 的内存生命周期

cpp 复制代码
#include <iostream>
using namespace std;

class LifecycleDemo {
public:
    LifecycleDemo() { cout << "构造函数" << endl; }
    ~LifecycleDemo() { cout << "析构函数" << endl; }
};

LifecycleDemo globalObj;  // 全局对象,main开始前构造,main结束后析构

void test_lifecycle() {
    cout << "\n=== static 生命周期 ===" << endl;
    
    static LifecycleDemo staticLocalObj;  // 第一次调用时构造,程序结束时析构
    
    cout << "函数内部" << endl;
}  // staticLocalObj 不会在这里析构

int main() {
    cout << "=== main 开始 ===" << endl;
    
    demo_static_local();
    test_singleton();
    demo_static_member();
    demo_static_functions();
    demo_template_static();
    demo_static_assert();
    demo_connection_pool();
    
    test_lifecycle();
    test_lifecycle();  // staticLocalObj 不会再次构造
    
    cout << "\n=== main 结束 ===" << endl;
    return 0;
}
// 程序结束时:staticLocalObj 和 globalObj 析构

十、static 使用注意事项

cpp 复制代码
// 1. 初始化顺序问题
class A {
public:
    static int a;
    static int getA() { return a; }
};

class B {
public:
    static int b;
};

int A::a = B::b + 1;  // 危险!B::b可能还未初始化
int B::b = 10;

// 2. 静态函数不能是虚函数
class Base {
public:
    // virtual static void func();  // 错误!
};

// 3. 静态函数不能访问非静态成员
class Test {
    int x;
    static int y;
    
public:
    static void func() {
        // x = 10;  // 错误!不能访问非静态成员
        y = 20;     // 正确!可以访问静态成员
    }
};

// 4. 线程安全问题
class Counter {
    static int count;  // 多线程环境下需要加锁
    
public:
    static void increment() {
        // 需要线程安全保护
        count++;
    }
};
相关推荐
烛衔溟1 分钟前
C语言并发编程:Windows线程
c语言·c++·windows·性能优化·多线程·并发编程·线程同步
im_AMBER2 分钟前
Leetcode 97 移除链表元素
c++·笔记·学习·算法·leetcode·链表
悟空码字2 分钟前
SpringBoot + Redis分布式锁深度剖析,性能暴涨的秘密全在这里
java·spring boot·后端
奋进的芋圆3 分钟前
Spring Boot中实现定时任务
java·spring boot·后端
海奥华25 分钟前
Golang Channel 原理深度解析
服务器·开发语言·网络·数据结构·算法·golang
Jasmine_llq5 分钟前
《P3200 [HNOI2009] 有趣的数列》
java·前端·算法·线性筛法(欧拉筛)·快速幂算法(二进制幂)·勒让德定理(质因子次数统计)·组合数的质因子分解取模法
MindCareers6 分钟前
Beta Sprint Day 5-6: Android Development Improvement + UI Fixes
android·c++·git·sql·ui·visual studio·sprint
代码游侠7 分钟前
学习笔记——MQTT协议
开发语言·笔记·php
sww_10268 分钟前
xxl-job原理分析
java
星环处相逢8 分钟前
K8s 实战笔记:3 种发布策略 + YAML 配置全攻略
java·docker·kubernetes