7.12 — 作用域、持续时间和链接总结

作用域、持续时间和链接的概念引起了很多困惑,所以我们将额外花一节课来总结所有内容。其中有些内容我们尚未涉及,它们只是为了完整性/供以后参考而放在这里。

作用域总结

标识符的作用域决定了在源代码中何处可以访问该标识符。

  • 具有块(局部)作用域的变量只能从声明点到声明它们的块的末尾(包括嵌套块)访问。这包括:
    • 局部变量
    • 函数参数
    • 在块内声明的程序定义类型(例如枚举和类)
  • 具有全局作用域的变量和函数可以从声明点到文件末尾访问。这包括:
    • 全局变量
    • 函数
    • 在命名空间内或全局作用域中声明的程序定义类型(例如枚举和类)

持续时间总结

变量的持续时间决定了它何时创建和销毁。

  • 具有自动持续时间的变量在定义时创建,并在它们所属的块退出时销毁。这包括:
    • 局部变量
    • 函数参数
  • 具有静态持续时间的变量在程序开始时创建,并在程序结束时销毁。这包括:
    • 全局变量
    • 静态局部变量
  • 具有动态持续时间的变量由程序员请求创建和销毁。这包括:
    • 动态分配的变量

链接总结

标识符的链接决定了同一标识符在不同作用域中的声明是否引用相同的实体(对象、函数、引用等)。

局部变量没有链接。每个没有链接的标识符声明都引用一个唯一的对象或函数。

  • 具有无链接的标识符意味着同一标识符的另一个声明引用一个唯一的实体。其标识符具有无链接的实体包括:
    • 局部变量
    • 在块内声明的程序定义类型标识符(例如枚举和类)
  • 具有内部链接的标识符意味着同一翻译单元内同一标识符的声明引用相同的对象或函数。其标识符具有内部链接的实体包括:
    • 静态全局变量(已初始化或未初始化)
    • 静态函数
    • Const 全局变量
    • 匿名命名空间及其内部定义的任何内容
  • 具有外部链接的标识符意味着整个程序中同一标识符的声明引用相同的对象或函数。其标识符具有外部链接的实体包括:
    • 非静态函数
    • 非 const 全局变量(已初始化或未初始化)
    • Extern const 全局变量
    • Inline const 全局变量
    • 命名空间

如果具有外部链接的定义被编译到多个 .cpp 文件中(由于违反了单一定义规则),通常会导致重复定义链接器错误。此规则有一些例外(对于类型、模板、内联函数和变量)——我们将在以后的课程中讨论这些主题时进一步介绍它们。

另请注意,函数默认具有外部链接。它们可以通过使用 static 关键字设置为内部链接。

变量作用域、持续时间和链接总结

因为变量具有作用域、持续时间和链接,让我们用图表总结一下:

类型示例作用域持续时间链接备注
局部变量int x;自动
静态局部变量static int s_x;静态
动态局部变量int* x { new int{} };动态
函数参数void foo(int x)自动
内部非 const 全局变量static int g_x;全局静态内部已初始化或未初始化
外部非 const 全局变量int g_x;全局静态外部已初始化或未初始化
内联非 const 全局变量 (C++17)inline int g_x;全局静态外部已初始化或未初始化
内部常量全局变量constexpr int g_x { 1 };全局静态内部必须初始化
外部常量全局变量extern const int g_x { 1 };全局静态外部必须初始化
内联常量全局变量 (C++17)inline constexpr int g_x { 1 };全局静态外部必须初始化

前向声明总结

您可以使用前向声明来访问另一个文件中的函数或变量。声明变量的作用域与往常一样(全局变量的全局作用域,局部变量的块作用域)。

类型示例备注
函数前向声明void foo(int x);仅原型,无函数体
非常量变量前向声明extern int g_x;必须未初始化
Const 变量前向声明extern const int g_x;必须未初始化
Constexpr 变量前向声明extern constexpr int g_x;不允许,constexpr 无法前向声明

constexpr 变量(隐式 const)可以使用 const 变量前向声明进行前向声明。通过前向声明访问时,该变量将被视为 const(而不是 constexpr)。

什么是存储类说明符?

当用作标识符声明的一部分时,staticextern 关键字称为存储类说明符。在这种上下文中,它们设置标识符的存储持续时间和链接。

C++ 支持 4 种活动的存储类说明符:

说明符含义注意
extern静态(或 thread_local)存储持续时间和外部链接
static静态(或 thread_local)存储持续时间和内部链接
thread_local线程存储持续时间
mutable即使包含类是 const,也允许修改对象
auto自动存储持续时间在 C++11 中已弃用
register自动存储持续时间并提示编译器放置在寄存器中在 C++17 中已弃用

存储类说明符一词通常仅用于正式文档中。

guest
您的电子邮箱地址将不会被显示
发现错误?请在上方留言!
与勘误相关的评论在处理后将被删除,以帮助减少混乱。感谢您帮助使网站对每个人都更好!
来自 https://gravatar.com/ 的头像与您提供的电子邮箱地址相关联。
有回复时通知我:  
190 评论
最新
最早 最多投票
内联反馈
查看所有评论