一、C++的static 的 5 种主要用法
// 1. 静态局部变量(函数执行完后不被销毁,保持其值)
// 2. 静态全局变量(限制作用域在当前文件)
// 3. 静态成员变量(属于类而不是对象,所有对象共享)
// 4. 静态成员函数(属于类而不是对象,不能访问非静态成员)
// 5. 静态断言 (static_assert)
总结对比
| 特性 | 静态局部变量1 | 静态全局变量2 | 静态成员变量3 | 静态成员函数4 |
|---|---|---|---|---|
| 作用域 | 函数内部 | 文件内部 | 类作用域 | 类作用域 |
| 生命周期 | 程序运行期 | 程序运行期 | 程序运行期 | 程序运行期 |
| 内存位置 | 数据段 | 数据段 | 数据段 | 代码段 |
| 初始化 | 第一次执行时 | main()前 | main()前 | N/A |
| 线程安全 | C++11后是 | 否 | 否 | 否 |
最佳实践:
-
使用静态局部变量1实现单例模式
-
使用静态成员函数4作为工具函数
-
使用静态成员变量3记录类级别信息
-
避免过度使用静态变量(破坏封装性)
-
多线程环境下注意同步问题
二、静态局部变量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++;
}
};