The storage class specifiers are a part of the decl-specifier-seq of a name’s declaration syntax. Together with the scope of the name, they control two independent properties of the name: its storage duration and its linkage.
存储类型说明符有以下几类:
- auto:
- register:
- static:
- extern:
- thread_local:
- mutable:
解释:
- auto存储说明符
- extern存储类型说明符仅被允许在变量和函数的声明中使用(类成员函数或函数参数除外)。它会指定外部链接,并且从技术上讲不会影响存储持续时间,但是不能在自动存储持续时间对象的定义中使用它,因此所有外部对象都具有静态或线程持续时间。另外,使用extern并且没有初始化程序的变量声明不是定义。
知识补充
存储持续时间(storage duration)
一个程序中所有的对象都具有以下一种存储持续时间:
- 自动存储持续时间(automatic storage duration):这种对象的存储空间在封闭代码块的开头分配,并在结尾处重新分配。除了声明为static,extern或thread_local的那些对象外,所有本地对象都具有此存储持续时间。
- 静态存储持续时间(static storage duration):这种对象的存储空间在程序开始时分配,并在程序结束时释放。该对象仅存在一个实例。在名称空间(namespace)范围内声明的所有对象(包括全局名称空间)都具有此存储持续时间,同时包括使用静态(static)或外部(extern)声明的对象。有关使用此存储持续时间初始化对象的详细信息,请参见非局部变量和静态局部变量。
- 线程存储持续时间(thread storage duration):这种对象的存储空间在线程开始时分配,在线程结束时释放。每个线程都有自己的对象实例。只有声明为thread_local的对象才具有此存储持续时间。thread_local可以与static或extern一起出现,以调整链接过程。有关使用此存储持续时间初始化对象的详细信息,请参见非局部变量和静态局部变量。
- 动态存储持续时间(dynamic storage duration):通过使用动态内存分配功能,可以按请求分配和释放对象的存储。有关使用此存储持续时间初始化对象的详细信息,请参见new-expression。
链接
表示对象,引用,函数,类型,模板,名称空间或值的名称可能具有链接。如果名称具有链接,那它会指向在其他作用域声明的相同的名称代表的实体。如果在多个作用域中声明了变量,函数或具有相同名称的另一个实体,但是没有足够的链接,则将生成该实体的多个实例。
如下的链接可以被识别:
无链接(no linkage):
此时名称仅可以在它的命名空间内被引用。在代码块中声明的如下名称是无链接的:
- 没有被显式的声明为extern的变量(无视静态修饰符)
- 局部类以及这些类的成员函数
- 其他在块命名空间中的名称(例如typedef、enumeration、enumerator)
内部链接(internal linkage):
此时名称可以在它当前翻译单元(translation unit)中的所有作用域中被引用。在命名空间中声明的如下名称是内部链接的:
- static声明的变量、变量模板、函数、函数模板
- non-volatile non-template (since C++14) non-inline (since C++17) non-exported (since C++20) const-qualified variables (including constexpr) that aren’t declared extern and aren’t previously declared to have external linkage;
- data members of anonymous unions.
外部链接(external linkage):
此时可以从其他翻译单元(translation unit)的命名范围中引用该名称。具有外部链接的变量和函数也具有语言链接(language linkage),这使得可以链接以不同编程语言编写的翻译单元。
Any of the following names declared at namespace scope have external linkage, unless they are declared in an unnamed namespace or their declarations are attached to a named module and are not exported (since C++20):
- variables and functions not listed above (that is, functions not declared static, namespace-scope non-const variables not declared static, and any variables declared extern);
- enumerations
- names of classes, their member functions, static data members (const or not), nested classes and enumerations, and functions first introduced with friend declarations inside class bodies;
- names of all templates not listed above (that is, not function templates declared static).
在代码块中第一次进行如下声明的同样也进行外部链接:
- extern声明的名称和变量
- 函数名