施工提示

本博文尚在施工中,内容并未完成且可能变更。

变量基础

本节介绍初始化、声明、作用域等变量基础,以及 const 关键字。

合法标识符

C++ 中的标识符(用户定义的合法变量名)满足以下要求:

  • 只能包含大写字母、小写字母、数字与下划线 _

  • 只能以字母或者下划线开头

  • 大小写敏感

  • 不能与 C++ 关键字重名,如 auto, enum, new 等

  • 不能与 C++ 操作符替代名重名,如 and, not, not_eq 等

  • 其他受限于标准库保留字的要求:

    • 不能有连续两个下划线

    • 不能以”下划线 + 大写字母“开头

    • 定义在函数体之外的变量,不能以下划线开头

初始化

变量在定义时拥有一个特定值,称为初始化。例如,初始化整数(int)类型的变量:

int m = 1;
int n = 3.14;       // 被隐式地转换为了整数 3
int x = 17, y = 11; // 利用逗号初始化多个 int 变量

列表初始化 C++ 11 是一种现代 C++ 的初始化方法,使用花括号来完成初始化。它在隐式转换可能发生数据损失时,将会报错:

double d = 3.14159;
// 以下列表初始化将会报错,因为 double 到 int 的转换可能损失数据
int x {d};
int y = {d};

如果不给定初始值(即不进行显式初始化),变量将被默认初始化。

int x;  // 执行 int 类型的默认初始化,初始化为 0

警告

推荐在定义变量时总是显式地对其进行初始化,而不要依赖默认初始化。

在某些情况下,不给定初始值地定义变量时,变量可能不会被初始化(而不是被默认初始化)。访问未初始化变量会引起错误。

变量初始化不等于变量赋值。变量赋值是擦除现有值,并使用新值替代。

变量声明

如果要在多个文件中使用同一个变量,就需要用到变量声明。标准库中的 std::cout 就是一个例子:它定义在标准库中(只在一处定义),却通过头文件中的声明使其能为我们的代码所用(在多处声明后使用)。

  • 定义(definition):创建变量实体。变量只能被定义一次。

  • 声明(declaration):申请一个变量的名称并指明其类型,而不创建实体。 变量可以被多次(重复地)声明。

要声明一个变量,使用 extern 关键字,且不要对变量进行显式初始化:

extern int i;       // 声明 int 类型的变量 i
int j;              // 定义 int 类型的变量 j
extern int k = 1;   // 由于显式初始化,定义了变量 k

作用域

C++ 一般以花括号界定作用域。函数外部的作用域称为全局作用域,函数内部的称块作用域。

在内层作用域中,可以重新定义外层作用域中定义的同名变量。通过 :: 前缀,可以在内层作用域中显式地访问全局变量:

#include <iostream>

int g = 100;
int main() {
    std::cout << g << std::endl;    // 访问外层变量,输出 100
    int g = 7;
    std::cout << g << std::endl;    // g 在内层被重定义,输出 7
    std::cout << ::g << std::endl;  // 访问全局变量 g,输出 100
    return 0;
}

警告

在实践中,谨慎从内层调用外层变量,也尽量不要在内层重新定义与外层同名的变量。