说明符和限定符
有些被称为存储说明符,或者是cv限定符
存储说明符如下
auto; // 在C++11(不包含C++11)之前表示自动变量,C++11中用于自动类型推导,即C++11(不包含C++11)是存储说明符号,C++11(含C++11)以后不再是存储说明符
register; // 在C++11(不包含C++11)表示寄存器变量,在C++11(包含C++11)之后仅表示自动自动变量
static;
extern;
thread_local; //(C++11新增)
mutable;
除了thread_local可以跟extern和static结合外,在同一个声明中不可以出现多个修饰符号。
除了thread_local和mutable没有认识外,其他均在前面有说明
cv-限定符号
const;
volatile;
其中const表示当变量内存被初始化后,程序不能再对其进行修改。
而volatile表示即使程序代码没有对其进行修改,其值仍然可能发生变化。,该关键词的作用主要是更改编译器的优化能力,一般来说在一个程序中同时使用一个值两次,程序可能不是将其读取两次,而是第一次读取时顺手存到寄存器,第二次直接从寄存器取出,这种假设没有外部程序会影响该值,但是如果使用volatile修饰变量,编译器将每次重新读取该值。
mutable成员表示即使某个类或者成员为const,其中被mutbale修饰的成员也可以修改,实例如下
struct data{
char name[100];
mutable int accesses;
};
const data d = {
"Llonvne",
0
};
strcpy(d.name, "Lcosvle"); // 不被允许 d 为常量其成员不允许修改
d.accesses++; // 允许 虽然d 为常量,但是accesses被mutable修饰所以可以修改。
在C++中(此处不包括C语言),const对默认存储类型稍有影响,在默认情况下全局变量的链接性为外部的,但是被const修饰的全局变量的链接性为内部,也就是说在C++看来,全局const定义类似于使用了static修饰符号一样,下述两句语句完全等价
const int a = 1;
const static int a = 1;
C++修改了常量类型的规则,使得程序员更加轻松,假设将一组全局常量放在头文件,并在同一个程序的多个文件中使用这样的头文件,那么处理器将头文件包含到所有的源文件后,所有的源文件都将包含一份全局常量定义,如果全局的链接性是外部的,根据前面的单定义规则,这将出错,也就是说只有一组文件可以包含定义,而另外的文件必须使用extern来引用变量。另外只有未包含extern关键字的才能进行初始化。这将导致许多不必要的麻烦。
因此,**需要为某个文件使用一组定义,而其他文件使用另外一组声明,然而由于外部定义的const数据的链接性仍然是内部,因此可以在所有文件使用相同的声明。**所以C++鼓励将const声明写入头文件,由于const内部链接性,他不会违反单定义规则。
如果出于某种特殊的原因,需要某个常量的链接性为外部的,可以使用extern来修饰const常量,这将覆盖原来的const的内部链接性。
extern const int a = 0;
这种情况该变量与普通的外部链接性变量使用方法基本一致(除了他是常量),也就是必须在所有使用它的文件中使用extern声明他。
下述表格说明了与普通外部变量的区别
类型 | 定义方法 | 链接性 | 其他文件的使用方法 |
---|---|---|---|
常规外部变量 | 在所有代码块外部定义 | 外部链接性 | 使用extern声明变量后使用 |
const外部变量(内部链接性) | 在所有代码块外部定义,且被const修饰 | 内部链接性 | 如果包含了声明const外部变量的头文件,可以直接使用。 |
const外部变量 (外部链接性) | 在所有代码块定义,且被const和extern同时修饰 | 外部链接性 | 同时使用extern和const变量引用变量,且引用常量只能在一处初始化。 |
,如果在代码块内部创建常量,只有在该代码块中常量可用。