总目录 > 1 语言基础 > 1.4 C++ 语言基础 > 1.4.4 命名空间与作用域
前言
可能是目前最简短的一篇?因为实在不知道可以和哪一篇一起讲了。
然后重整 C++ 时补充了许多内容,诸如作用域和生命期等等,也就不是最短的一篇啦。
更新日志
20200903 - 增加作用域和全局/局部变量的介绍。
子目录列表
1、命名空间
2、作用域
3、生命期
1.4.4 命名空间与作用域
1、命名空间
C++ 另一大特性 —— 命名空间(namespace),用来解决复杂项目中名字可能出现冲突的问题——比如某项目由 jk 和 bebe 共同完成,而他俩在定义变量名时总是重复,比如都使用了 vis 作为标记数组,那么就可以使用 namespace 来对各自的工作空间进行切割:
1 #include <bits/stdc++.h> 2 3 namespace jk { 4 int vis[20]; 5 } 6 7 namespace bebe { 8 int vis[20]; 9 } 10 11 int main() { 12 jk :: vis[1] = 1; 13 bebe :: vis[1] = 0; 14 return 0; 15 }
当然并非每次都需要强调这是谁的 vis。使用 “using namespace ” + 空间名,相当于是划分地盘:
1 #include <bits/stdc++.h> 2 3 namespace jk { 4 int vis[20]; 5 } 6 7 namespace bebe { 8 int vis[20]; 9 } 10 11 int main() { 12 using namespace jk; 13 vis[1] = 1; 14 bebe :: vis[1] = 0; 15 return 0; 16 }
这里表示,主程序这一块都是 jk 的,jk 住在这里了,那么他自己的东西就不用再强调是谁的了,vis[1] 等价于 “jk :: vis[1]”,而外人 bebe 仍需标明。
所以,平时竞赛最常用的 using namespace std 是指什么?是 C++ 默认提供的一套标准命名空间,里面包含 cin, cout, endl, ... 等等。
当然,除了上述这样允许访问某命名空间的任何成员,也可以选择仅访问其中一个成员,比如 using std :: cin,等等。
2、作用域
作用域是指标识符在程序中的有效范围,大致分为全局作用域、局部作用域和文件作用域;按照作用域范围从大到小分为程序作用域、文件作用域、类作用域、函数作用域和块作用域。
① 程序作用域:标识符在整个程序范围内有效。如果一个程序由多个文件组成,具有这种作用域的标识符在该程序的各个文件中均可使用,只能在其中一个文件中定义一次,其他文件用 extern 声明;
② 文件作用域:指一个文件中所有函数定义以外定义的名字,有效范围为整个文件;
③ 类作用域:在类范围内有效的标志符;
④ 函数作用域:在函数范围内有效的标志符;
⑤ 块作用域:使用 '{' 和 '}' 可以构成一个语句块,在其中定义的标识符只能在块中使用(类与函数本质上也是一个语句块);
在命名空间中我们使用了一个符号 —— ::,它叫做作用域限定符。一旦当前作用域中找到了对应的名字,编译器就会忽略更外层作用域的同名实体。也就是说,如果某个局部变量和全局变量同名,局部变量优先级更高,这时可以用 :: 来存取全局变量的值。
3、全局变量和局部变量
根据变量的作用域范围,变量可以划分为全局变量和局部变量。在某个语句块(包括类,函数等)中内部定义的变量和函数参数是局部变量,只能在定义它的块中使用;而不存在于任何块中的变量,则是全局变量,其有效范围从文件中定义位置开始到文件结束。
生命期是指标识符在程序中的生存周期。变量的生命期指变量在内存中存在的时间,除了取决于定义位置,还取决于它的变量类型,不同变量类型,所占用的内存区域也是不同的。
一个程序在运行期间,程序代码和数据会被分别存储在 4 个不同的内存区域中:
① 程序代码区:存储程序所有代码,包括主函数和子函数;
② 全局数据区:存储程序的全局数据(全局变量)和静态数据(static),所有未初始化变量会被系统自动初始化为 0;
③ 栈区:存储程序的局部变量,只有当其对应语句块被调用时,系统才会为其建立堆栈并分配空间,且不会进行初始化;
④ 堆区:存储程序的动态数据(new, malloc 等动态分配内存的方式)。
全局变量和静态变量的生命期较长,局部变量生命期较短。其中,静态变量又分为静态全局变量和静态局部变量,静态局部变量虽然作用域局限于定义它的语句块,但它的生命期和全局变量一样,即程序结束时才会被释放。
平时编写代码时,关于全局变量和局部变量我们要注意什么?首先前面我们提到,同名的前提下,局部变量优先级高于全局变量,在不确定的情况下最好避免变量同名;其次,局部变量不会自动初始化,如果没有初始化,变量会拥有一个不确定的值,往往会直接导致结果错误或运行错误。