在C++中创建变量时,前面有时会有一些修饰符,这里总结一下。
大体分为两个类别:存储说明符和cv-限定符。
存储说明符
存储说明符有下面这些:
- auto
- register
- static
- extern
- mutable
auto修饰符的变量时自动变量,如果变量没有任何修饰符,默认就是自动变量,其作用域在函数内部。
register修饰变量将创建一个寄存器变量,理念在于CPU访问寄存器中的值比访问普通存储在堆栈中的值速度要快,声明方法:
register int count_fast;
需要注意的是,编译器并不一定会满足将变量放在寄存器中的要求(有可能已被占用等等),而且寄存器中无内存地址,所以寄存器变量不能用地址操作符。
static修饰静态变量。要注意静态变量使用范围:
int global = 1000;// 在函数外声明,文件内外皆可使用
// 此时如果其他文件还想创建global同名变量,要么用extern声明(此时用的还是同一个,共享了变量),要么用static声明来隐藏这个大全局global(此时是新的变量)
static int one_file = 50;// 在函数外使用static声明,只在文件内各个函数可使用
void func (int n) {
static int count = 0;// 在函数内用static声明,只能在函数内使用,但是无论函数是否执行,变量都存在,且多次调用时其值不会重新初始化,而是保持上一次的结果
int lama = 0;// 普通变量,只能在函数内使用,函数不执行就不会存在
}
函数内创建与外部静态变量同名的变量时,将使用自己创建的,但是可以用::操作符表示使用外部的:
int global = 1000;
void func () {
int global = 500;
cout << global << endl;// 500
cout << ::global << endl;// 1000
}
extern修饰的变量表示引用声明,假设文件1声明了一个外部变量,文件2要使用它,必须使用extern来修饰,因为不能创建两个同名的外部变量,如上文所述。
// file1.cpp
int global = 1000;
// file2.cpp
extern int global;
mutable修饰的变量,顾名思义,表示变量可变,那什么时候不可变呢?在下文要说的使用const修饰符修饰时,变量应该是不可变的,但是可能有这种用法:
struct person {
char name[30];
mutable int age;
};
const person me = {"Cloudox", 24};
strcpy(me.name, "Cloud");// 这是不允许的,因为结构体person的实例me是用const修饰的
me.age++;// 但这又是允许的,因为结构体person的成员age用mutable修饰了
cv-限定符
cv限定符只有两种:
- const
- volatile
这也是为什么它叫cv限定符,取首字母嘛。
const关键字上文已经说过了,很常用,表示变量的内存初始化后,程序不能对它进行修改了。
volatile修饰的变量时告诉程序,即使程序代码本身没有对变量的内存单元进行修改,它却也可能发生变化。
为什么会发生变化呢?因为假设你指针指向某个硬件位置,其中包含来自串行端口的时间或信息,这就有可能硬件本身改变它,而不是你程序去改变它。
那为什么要告诉程序它可能变化呢?因为假设编译器发现程序在几条语句中都使用了某个变量,那么为了优化,它不会让程序去查多次,而是缓存到寄存器中。这种优化是在变量本身不会被程序改变的前提下的,但是如果硬件改变了变量值,那就不能用这种优化了。因此volatile关键字实际上也就是告诉编译器,不要对这个变量做这种优化。
网友评论