链接和作用域 C++快速入门42

链接和作用域

 

让编程改变世界

Change the world by program


 

链接和作用域

  前边我们已经开始创建由多个文件构成的项目,是时候再来讨论下更复杂的变量作用域了。 简单的理解,变量的作用域就是你可以在什么范围内访问这个变量。   地球人都知道,一个在任何函数之前定义的变量可以在任何一个函数里使用(这是一个全局变量),而在某个函数里定义的变量只能在那一个函数里使用(这是一个局部变量)。 那么,当一个项目由多个文件构成时,变量的作用域也会受到一定的影响!   与作用域有关的另一个概念是链接,当你同时编译多个文件时:

g++ -o test main.cpp rational.cpp

  每个源文件都被称为一个翻译单元(translation unit),在某一个翻译单元里定义的东西在另一个翻译单元里使用正是链接发挥作用的地方。 作用域、链接和存储类是相互关联的概念,它们有许多共同的术语,只是观察和描述问题的角度不同罢了。  

存储类(storage class)

  每个变量都有一个存储类,它决定着程序将把变量的值存储在计算机上的神马地方、如何存储,以及变量应该有着怎样的作用域。 默认的存储类是auto(自动),但你不会经常看到这个关键字,因为它是默认的,阴魂不散的!   自动变量存储在称为栈(stack)的临时内存里并有着最小的作用域,当程序执行到语句块或函数末尾的右花括号时,它们将被系统回收(栈回收),不复存在。 与auto不同的是static,static变量在程序的生命期内将一直保有它的值而不会消亡,因为它们是存储在静态存储区,生命周期为从申请到程序退出(和全局变量一样)。   另外我们稍后就会提到的,一个static变量可以有external或internal链接。 第三种存储类是extern,它在有多个翻译单元时非常重要。这个关键字用来把另一个翻译单元里的某个变量声明为本翻译单元里的一个同名全局变量。 注意,编译器不会为extern变量分配内存,因为在其他地方已经为它分配过内存。   用extern关键字相当于告诉编译器:“请相信我,我发誓我知道这个变量在其他翻译单元里肯定存在,它只是没在这个文件里声明而已!” 还有一个存储类是register,它要求编译器把一个变量存储在CPU的寄存器里。但有着与自动变量相同的作用域。 register变量存储速度最快,但有些编译器可能不允许使用这类变量。  

变量的链接和作用域

链接是一个比较深奥的概念,所以我们尽可能以浅显的文字来解释它。  

在使用编译器建议程序时,它实际上是由3个步骤构成:

  1. 执行预处理器指令;
  2. 把.cpp文件编译成.o文件;
  3. 把.o文件链接成一个可执行文件。
  如今的编译器都是一次完成所有的处理,所以你看不到各个步骤(学习Win32汇编的童鞋懂~) 步骤一前边我们已经讨论过:执行预处理指令,例如把#include指令替换为相应的头文件里的代码,总的效果是头文件里的代码就像从一开始就在.cpp文件里似的。     步骤二是我们司空见惯的事情:把C++代码转换为一个编译目标文件,在这一步骤里,编译器将为文件里的变量分配必要的内存并进行各种错误检查。 如果只有一个C++源文件,步骤三通常只是增加一些标准库代码和生成一个可执行文件。 但当你同时编译多个源文件来生成一个可执行文件的时候,在编译好每一个组件之后,编译器还需要把它们链接在一起才能生成最终的可执行文件。 当一个编译好的对象(即翻译单元)引用一个可能不存在于另一个翻译单元里的东西时,潜在的混乱就开始出现了。   链接分为三种情况,凡是有名字的东西(函数、类、常量、变量、模板、命名空间,等等)必然属于其中之一:外连接(external),内链接(internal)和无链接(none)。   外链接的意思是每个翻译单元都可以访问这个东西(前提是只要它知道有这么个东西存在)。 普通的函数、变量、模板和命名空间都有外链接。 就像main.cpp可以使用rational.cpp文件里定义的类和函数一样,其实我们一直在使用,只是今天我们来一次总结。   说到变量,你可以这样试一试: [codesyntax lang="c"]
// this.cpp
int i1 = 1;

// that.cpp
int i2 = i1;
[/codesyntax]   不用试了,一看就有问题,对不对?!在编译that.cpp文件时,编译器并不知道i1变量的存在。 为了解决这个问题,我们可以在that.cpp里使用extern关键字去访问第一个翻译单元的变量。 [codesyntax lang="c"]
// this.cpp
int i1 = 1;

// that.cpp
extern int i1;
int i2 = i1;
[/codesyntax]   内链接的含义是:在某个翻译单元里定义的东西只能在翻译单元里使用,在任何函数以外定义的静态变量都有内链接: [codesyntax lang="c"]
// this.cpp
static int d = 8;

// that.cpp
static int d = 9;
[/codesyntax]   这两个文件各有一个同名的变量,但它们是毫不相干的两样东西。 最后,在函数里定义的变量只存在于该函数的内部,根本没有任何链接(none)。   小甲鱼相信,现在众鱼油的心里肯定有十万只草泥马在奔腾!   但是,如果你能把上面这些关于作用域和链接的事情都搞清楚,就会发现这几个话题其实是彼此紧密相关的,把课件好好再看一遍。 下节课给大家带来巩固这些个概念的练习,敬请期待和准时收看。 [buy] 获得所有教学视频、课件、源代码等资源打包 [/buy] [Downlink href='http://urlxf.qq.com/?qQfINnA']视频下载[/Downlink] [Downlink href='http://kuai.xunlei.com/d/LFGSRSYLNSYD']备胎下载[/Downlink]
原文地址:https://www.cnblogs.com/LoveFishC/p/3846225.html