这三者都能对变量的访问和存储行为产生影响,但是区别很大
总结
- volatile: 变量的值可能随时发生变化。要求编译器每次访问该变量时都要重新读取其值,而不是使用已经缓存的值。
extern:
告诉编译器,变量在其他文件中定义,当前文件只需要使用它,不需要重新定义。- static:每次调用
func
函数时,static变量的值都会被保留并自增,不会被重新初始化。
volatile
用于确保变量的实时性,可靠性
用于告诉编译器一个变量可能被意外修改的标记,即这个变量的值可能随时发生变化。它告诉编译器不要优化掉对这个变量的读取操作,该变量可能会被外部修改,从而要求编译器每次访问该变量时都要重新读取其值,而不是使用已经缓存的值。这种行为可以用来确保变量的实时性,特别是在多线程或中断处理程序中。常用于多线程环境下共享内存的变量、设备驱动程序中对硬件寄存器的访问等场景。
for(volatile int i=0; i<100000; i++); // 它会执⾏,不会被优化掉
编译器在编译源代码时,会尽可能地对代码进行优化,以使得生成的目标代码更加高效、快速、节省内存等。比如在上面的代码中,如果不添加volatile关键字,这个没有执行语句的循环就会被优化掉。编译器的优化有以下几种:
- 注册变量寄存器优化:编译器会尽量将变量存储在 CPU 寄存器中,以提高变量访问的速度。这种优化通常适用于变量的作用域为局部变量、变量的生命周期较短、变量的大小适中等情况。
- 常量折叠优化:编译器会尝试将表达式中的常量合并,从而减少目标代码中的常量数量,提高程序的执行效率。
- 循环展开优化:编译器会将循环中的多个迭代展开为单个迭代,从而减少循环控制器的开销,提高程序的执行效率。
- 内存对齐优化:编译器会将变量存储到内存中时,考虑到 CPU 访问内存的速度等因素,尽量将变量按照一定的规则进行对齐,以提高变量的访问速度。
在某些情况下,变量优化也可能导致程序出现错误,例如在多线程环境下使用volatile
变量时,如果编译器将变量的读取操作优化掉,就可能导致程序出现意外的行为,因此在这种情况下应该避免对变量进行优化。
extern
比如在一个文件中定义了一个全局变量
//文件1.cpp
int g_var = 10;
int main() {
cout << g_var ;
return 0;
}
在另一个文件中使用这个变量:
//文件2.cpp
extern int g_var = 10;
int main() {
cout << g_var ;
return 0;
}
extern
关键字告诉编译器,g_var
变量在其他文件中定义,当前文件只需要使用它,不需要重新定义。
static
用于实现数据的隐藏和封装
void func() {
static int count = 0;
cout << count << " ";
count++;
}
int main() {
for (int i = 0; i < 2; i++) {
func();
}
for (int i = 0; i < 5; i++) {
func();
}
return 0;
}
在这个示例中,count
变量被声明为static
,这意味着每次调用func
函数时,count
变量的值都会被保留并自增,而不会被重新初始化。
将变量的作用域限定在当前文件或当前函数内部,从而实现数据的隐藏和封装。这种行为可以用来防止变量被其他文件或函数访问,并确保变量在不同的函数调用之间保持其值不变。
实现多个对象之间的数据共享 + 隐藏,并且使⽤静态成员还不会破ࣕ隐藏原则