C++系列:变量作用域和初始化
这篇文章介绍变量作用域和初始化的相关概念。
概述
变量提供一个具名的、可供程序操作的存储空间。C++ 中每一个变量都有其类型,数据类型决定着所占内存的大小和布局方式、该空间能够存储的值的范围,以及变量能参与的运算。
变量初始化
C++ 语言定义了初始化的好几种不同形式,例如想定义一个名为 units_sold 的 int 变量并初始化为 0, 以下的4条语句都可以做到这一点:
1 | int units_sold = 0; |
作为 C++11 新标准的一部分,用花括号来初始变量得到了全面应用,这种初始化的形式被称为列表初始化(list initialization)。
默认初始化
如果定义变量时没有指定初始值,则变量被默认初始化,此时变量被赋予了“默认值”。默认值到底是什么由变量类型决定,同时定义变量的位置也会对此有影响。
如果是内置类型的变量未被显式初始化,它的值由定义的位置决定。定义于任何函数体之外的变量被初始化为 0, 定义在函数体内部的内置类型变量将不被初始化。一个未被初始化的内置类型变量的值是未定义的,如果试图拷贝或以其它形式访问此类值将引发错误。
类对象各自决定其初始化的方式,而且,是否允许不经初始化就定义对象也由类自己决定。
总结:
- 函数体外的变量默认初始化为 0;
- 函数体内的变量默认不初始化,其值未定义;
- 类对象自行决定是否初始化。
名字的作用域
不论是在程序的什么位置,使用到的每个名字都会指向一个特定的实体:变量、函数、类型等。然而,同一个名字如果出现在程序的不同位置,也可以指向的是不同实体。
作用域 (scope) 是程序的一部分,在其中名字有其特定的含义。 C++ 语言中大多数作用域都以花括号分隔。
同一个名字在不同的作用域中可能指向不同的实体。名字的有效区域始于名字的声明语句,以声明语句所在的作用域末端为结束。
1 | int main() |
以上面程序为例,它定义了 3 个名字: main, sum 和 val, 同时使用了命名空间名字 std, 该空间提供了 2 个名字 cout 和 cin 供程序使用。
在程序中提供了三种作用域:
- 全局作用域(global scope): 定义于所有花括号之外,如 main, 一旦声明之后,全局作用域内的名字在整个程序的范围内都可以使用;
- 块作用域(block scope): 定义于花括号之内,如 sum, 它定义于 main 函数所限定的作用域之内,从声明 sum 开始直到 main 函数结束为止都可以访问它,但是出了 main 函数所在的块就无法访问了。
- 语句作用域(statement scope): 名字 val 定义于 for 语句内,在 for 语句之内可以访问 val, 但是在 main 函数的其它部分就不能访问它了。
建议:当你第一次使用变量时再定义它。