C++中的static关键字

static的引入

static是C++中的修饰符,可以修饰变量和函数,用来控制变量的存储方式和可见性。

一般情况下,函数内部的变量,在程序运行到它的定义时,会在栈内为其分配内存,在函数执行结束后释放。如果我们想要某些变量(例如记录函数调用次数的变量)的生命周期不局限于函数执行期间,在执行结束后不释放而是继续保留,并且在同时确保将其作用域限制在函数内部,那么一般的变量和全局变量(虽然生命周期不局限于函数执行期间,但是其作用域也不局限于函数内部)都无法满足我们的需求,因此引入了static关键字来解决这个问题。

static的使用

静态局部变量

如前文所述,函数内的局部变量可以用static修饰,将其声明为静态局部变量,这样它的生命周期贯穿整个程序运行期间的同时作用域也能限制在函数内部。

C++11 标准规定,静态局部变量的初始化只会发生一次,因此在多线程环境下,初始化过程是线程安全的。

1
2
3
4
5
6
7
8
9
10
11
12
void func() {​
static int count = 0; // 静态局部变量​
count++;​
std::cout << "Count: " << count << std::endl;​
}​

int main() {​
func(); // 输出: Count: 1​
func(); // 输出: Count: 2​
func(); // 输出: Count: 3​
return 0;​
}

静态全局变量

在全局作用域中,static 关键字可以用来限制变量的链接性可见性。​
​静态全局变量只能在定义它的文件中访问,其他文件无法访问该变量

1
2
3
4
5
// file1.cpp​
static int globalVar = 42; // 静态全局变量​

// file2.cpp​
extern int globalVar; // 错误: globalVar 在 file2.cpp 中不可见

类的静态成员变量

  • 类的静态成员变量属于类本身,而不是某个对象
  • 静态成员变量在所有对象间共享
  • 静态成员变量一定要在类外初始化
    • 因为静态成员属于整个类,而不属于某个对象,如果在类内初始化,则该类再一次创建对象时静态成员将再一次被“初始化”(变成初始值),会修改其他对象对该静态变量操作的意图,可能发生意外。
    • C++11 起,允许对常量静态成员变量在类内部进行初始化
  • 静态成员变量可以直接通过类名访问,因为它本身就位于类空间而不是普通成员空间
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class MyClass {​
public:​
static int staticVar; // 静态成员变量声明​
};​

int MyClass::staticVar = 0; // 静态成员变量定义​,注意这里需要有类型标识符

int main() {​
MyClass obj1;​
MyClass obj2;​

obj1.staticVar = 10;​
std::cout << "obj2.staticVar: " << obj2.staticVar << std::endl; // 输出: 10​

MyClass::staticVar = 20;​
std::cout << "obj1.staticVar: " << obj1.staticVar << std::endl; // 输出: 20​

return 0;​
}​

类的静态成员函数

  • 静态成员函数属于类本身,而不是某个对象。
  • 由于this指针指向的是某个具体的对象,因此静态成员函数没有this指针
  • 静态成员函数只能访问静态成员变量和静态成员函数,因为它没有this指针
1
2
3
4
5
6
7
8
9
10
11
class MyClass {​
public:​
static void staticFunc() { // 静态成员函数​
std::cout << "Static function called." << std::endl;​
}​
};​

int main() {​
MyClass::staticFunc(); // 通过类名调用静态成员函数​
return 0;​
}

修饰普通函数

static用来修饰普通函数时,其作用是限制函数的链接性,当一个普通函数被 static 修饰时,它的符号(函数名)不会被导出到全局符号表中,因此其他文件无法通过 extern 声明来引用该函数。这种特性可以用于隐藏函数的实现细节,避免命名冲突,或者限制函数的作用域。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// file1.cpp​
static void hiddenFunction() { // static 修饰的普通函数​
std::cout << "This function is hidden from other files." << std::endl;​
}​

void publicFunction() {​
hiddenFunction(); // 可以在本文件中调用​
}​

// file2.cpp​
extern void hiddenFunction(); // 错误: hiddenFunction 在 file2.cpp 中不可见​

void anotherFunction() {​
hiddenFunction(); // 错误: hiddenFunction 在 file2.cpp 中不可见​
}​

匿名空间

要想实现将符号的作用域限制在本文件中,除了用static修饰外,还可以使用匿名空间来实现

1
2
3
4
5
6
7
8
9
10
11
12
13
// file1.cpp​
namespace { // 匿名命名空间​
void hiddenFunction() {​
std::cout << "This function is hidden from other files." << std::endl;​
}​
}​

void publicFunction() {​
hiddenFunction(); // 可以在本文件中调用​
}​

// file2.cpp​
extern void hiddenFunction(); // 错误: hiddenFunction 在 file2.cpp 中不可见​

static的区别在于

  • static 是 C 语言风格的用法,而匿名命名空间是 C++ 特有的特性。​
  • 匿名命名空间可以隐藏类、变量、函数等多种符号,而 static 只能用于函数和变量。​
  • 匿名命名空间更符合 C++ 的现代编程风格,推荐优先使用。

参考


C++中的static关键字
https://guts.homes/2025/06/13/cpp-static/
作者
guts
发布于
2025年6月13日
许可协议