













今天想讲解一下C++中的static关键字的使用 --- 改变生命周期和改变作用域(链接属性)
static关键字的作用包括3条
1. static最重要的功能是隐藏
2. static变量存放在静态存储区,所以它具备持久性
3. 也是因为static变量存放在静态存储区,所以它默认值是0
全局变量
我们知道,在C++中,全局变量是在所有函数体的外部定义的,程序的所有部分(其他文件的代码)都可以使用. 全局变量不受作用域的影响,它的生命周期一直到程序的结束。
全局变量也不是可以随便写在哪里,它得出现在所有的function, main,类定义之外的文件作用域里。
extern int age;),那得确保某处有且仅有一个定义,否则链接失败int age = 20;),否则多文件包含会触发 ODR 违规,报错 multiple definition of 'age对于全局变量,extern声明和定义的区别很关键
extern不是 “声明一个全局变量”,而是 “告诉编译器,这是个全局变量,在别处定义了,我只是用它,不占用内存”
int age = 300; ----- 分配存储,只能出现一次extern int age; ----- 不分配空间,可出现在多个文件中(包括头文件)extern int age = 10; ---- = 10 让它变成定义,导致重复定义static关键字 第1条解析 -- 隐藏
我们来看一个例子
a.cpp
char x = 'A'; //全局变量 void msg() { printf("Hello\n"); }
b.cpp
int main(void) { extern char x; // extern关键字表示这是来自外部的一个全局变量 printf("%c ", x); (void)msg(); return 0; }
输出结果 A Hello
这个例子中,我们可以看到,在a.cpp定义的全局变量x和全局函数msg, 都可以在b.cpp中使用
那么,现在我想a.cpp中的这个全局变量和全局函数对其他文件隐藏,也就是说,其他文件比如b.cpp压根就看不到它,当然也不能使用它,怎么办呢 => 这就要用到static关键字
在全局作用域(函数外,类外)使用static,它的核心作用是内部链接
含义: 被修饰的变量,函数或者对象, 只对“当前编译单元(.cpp文件)”可见
效果: 其他.cpp文件即使使用extern,也无法链接到它
#include <iostream> using namespace std; //static 隐藏全局变量,仅本文件可见 static int g_inner_val = 10; //static 隐藏全局函数,仅本文件可见 static void inner_func() { cout << "inner_func: 仅test.cpp可见" << endl; } //static 隐藏全局结构体实例, 仅本文件可见 static struct InnerObj { void show() { cout << "g_inner_val = " << g_inner_val << endl; } } g_inner_obj; void public_func() { cout << "public_func: 外部可调用" << endl; inner_func(); //本文件内部可以调用static 函数 g_inner_obj.show(); //本文件内部可以调用static 对象 }
static关键字 第2条解析 -- 改变存储期,保持变量内容的持久
存储在静态数据区的变量会在程序刚开始运行时就完成初始化,也是唯一的一次初始化. 共有2种变量存储在静态存储区,全局变量和static变量 (像上面例子在全局变量前面加上static关键字,那这个变量是静态全局变量,它既是全局变量,又是静态变量,static的作用是隐藏它)
生命周期: 程序启动时分配内存(静态存储区),程序结束才释放
我们来看一个例子,在函数内部的局部变量前加上static关键字,让这个局部变量存储在静态存储区 => 它经常用来实现计数器,单列模式
Counter.cpp
#include <iostream> using namespace std; void TestCounter() { // 静态局部变量,只会初始化1次 static int count = 0; count++; cout << "count = " << count << endl; } int main() { TestCounter(); // 1 TestCounter(); // 2 TestCounter(); // 3 return 0; }
上面的例子中,可以看出,用static来修饰函数内的局部变量,有以下作用
保留变量值:函数多次调用时,变量会保留上一次的值适合需要持久化状态的场景 (如 计数,缓存)static关键字修饰类的成员
上面我们已经讲到static关键字修饰全局变量/函数,修饰函数内的局部变量。现在我们想来说一说用static关键字来修饰类中的成员,包括成员变量和成员函数
static静态数据成员是类的成员,而不是对象的成员
类的static静态成员函数属于整个类,而不是类的对象,所以它没有this指针. 这就导致了它仅能访问类的静态数据和静态成员函数
关于这点,可以参看问我以前写的文章 https://www.cnblogs.com/wphl-27/p/18011014
1. static类的静态成员变量
可通过类名::变量名 或 对象.变量名 访问2. static类的静态成员函数
直接通过类名::函数名 () 调用,无需创建对象。总结
| 修饰场景 | 核心作用 | 生命周期 | 作用域 |
|---|---|---|---|
| 局部变量 | 持久化值,只初始化 1 次 | 程序全程 | 函数内 |
| 全局变量 / 函数 | 仅当前文件可见,防冲突 | 程序全程 | 当前源文件 |
| 类成员变量 | 所有对象共享,类独有 | 程序全程 | 类作用域 |
| 类成员函数 | 无 this 指针,类直接调用 | - | 类作用域 |
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。