C++作用域、链接性和存储持续性(下)

发布于 2021-09-18  55 次阅读


从变量存储持续性看变量定义

1、自动存储持续性

这类对象的存储在外围代码块开始时分配,并在结束时解分配。

  • 未声明为 staticextern 或 thread_local 的所有局部对象均拥有此存储期。(是局部对象因此拥有块作用域和无链接性)

2、静态存储持续性

拥这类对象的存储在程序开始时分配,并在程序结束时解分配。这类对象只存在一个实例。

所有声明于命名空间(包含全局命名空间)作用域的对象,加上声明带有 static 或 extern 的对象均拥有此存储期。但可能具有不同的链接性。

3、动态存储持续性

使用new创建的对象拥有动态存储持续性,但这指的是这块内存。操作这个对象的变量->指针或引用有其各自的链接性、作用域和存储持续性。

动态存储持续性的对象直到使用delete或程序结束才会被释放。

4、线程存储持续性

使用关键字thread_local声明的变量拥有线程存储持续性 。其行为类似静态存储持续性。只不过声明周期不是整个程序,而是线程。只有声明为 thread_local 的对象拥有此存储期。 thread_local 能与 static 或 extern 一同出现,它们用于调整链接。

从链接性看变量定义

1、无链接

声明于块作用域的下列任何名字均无链接:

  • 未显式声明为 extern 的变量(不管有没有 static 修饰符);
  • 局部类及其成员函数;
  • 声明于块作用域的其他名字,例如 typedef、枚举及枚举项。

未指定为拥有外部、模块 (C++20 起)或内部链接的名字同样无链接,这与其声明所处的作用域无关。

2、内部链接

声明于命名空间作用域的下列任何名字均具有内部链接:

  • 声明为 static 的变量、变量模板 (C++14 起)、函数或函数模板;最常见的:static全局变量 -> 内部链接
  • 未声明为 extern 且先前未声明为具有外部链接的非 volatile 非模板 (C++14 起)非 inline (C++17 起)且未被导出 (C++20 起)的 const 限定的变量(包含 constexpr)最常见的:const全局变量 -> 内部链接
  • 匿名联合体的数据成员。
  • 所有声明于匿名命名空间或匿名命名空间内的命名空间中的名字,即使显式声明为 extern,也均拥有内部链接。

3、外部链接

 声明于命名空间作用域的下列任何名字均具有外部链接,除非这些名字在匿名命名空间内声明或它们声明于具名模块且未被导出(C++20),具有外部链接的变量和函数也具有语言链接

  • 以上未列出的变量与函数(即未声明为 static 的函数、命名空间作用域内未声明为 static 的非 const 变量,和所有声明为 extern 的变量);
  • 枚举;--> 这里有个坑,详见C++枚举类型
  • 类以及其成员函数、静态数据成员(不论是否 const)、嵌套类及枚举,及首次以类体内的 friend 声明引入的函数的名字;
  • 所有未列于上的模板名(即未声明为 static 的函数模板)。

任何首次声明于块作用域的下列名称拥有外部链接:

  • 声明为 extern 的变量名;
  • 函数名。

4、模块链接

如果声明于命名空间作用域的名字附着到具名模块,未被导出且无内部链接,则其拥有模块链接。


当其他人都认为你要鸽的时候,你鸽了,亦是一种不鸽