作用域(scope)描述了在文件(翻译单元)的多大范围可见。
链接性(linkage)描述了名称如何在不同单元间共享。链接性为外部的名称可在文件间共享,链接性为内部的名称只能由一个文件中的函数共享。
(1) 自动变量只在包含它们的函数或代码块中可见。
//autoscp.cpp - 阐明自动变量的范围
#include<iostream>
void oil(int x);
int main()
{
using namespace std;
int texas = 31;
int year = 2011;
cout << "In main(), texas = " << texas << ", &texas = ";
cout << &texas << endl;
cout << "In main(), year = " << year << ", &year = ";
cout << &year << endl;
oil(texas);
cout << "In main(), texas = " << texas << ", &texas = ";
cout << &texas << endl;
cout << "In main(), year = " << year << ", &year = ";
cout << &year << endl;
cin.get();
return 0;
}
void oil(int x)
{
using namespace std;
int texas = 5;
cout << "In oil(), texas = " << texas << ", &texas = ";
cout << &texas << endl;
cout << "In oil(),x = " << x << ", &x = ";
cout << &x << endl;
//开启一个板块
{
int texas = 113;
cout << "In block, texas = " << texas;
cout << ", &texas = " << &texas << endl;
cout << "In block,x = " << x << ", &x = ";
cout << &x << endl;
}
//板块结束
cout << "post-block texas = " << texas;
cout << ", &texas = " << &texas << endl;
}
![](https://i-blog.csdnimg.cn/blog_migrate/6cabe8290c9242189f168d810aab2ec7.png)
当程序调用oil()时,这些变量仍留在内存中,但不可见。为两个新变量(x和texas)分配内存,从而使它们可见。 在程序执行到oil()中的内部代码块时,新的texas将不可见。当程序流程离开该代码块时,将释放最新的texas使用的内存,而第二个texas再次可见。当oil()函数结束时,texas和x都将过期,而最初的texas和year再次变得可见。
(2) 静态变量在整个程序执行期间一直存在。编译器分配固定的内存块来存储所有的静态变量。
与C语言一样,C++也为静态存储持续性变量提供了三种链接性:外部链接性(可在其他文件中访问)、内部链接性(只能在当前文件中访问)和无链接性(只能在当前函数或代码块中访问)。
1. 创建链接性为外部的静态持续变量:必须在代码块外面声明它;
2. 创建链接性为内部的静态持续变量:必须在代码块外面声明它,并使用static限定符;
3. 创建没有链接性的静态持续变量:必须在代码内声明它,并使用static限定符。
int global = 1000; //静态持续,外部链接
static int one_file = 50; //静态持续,内部链接
int main() {
...
}
void func1(int n) {
static int count = 0; //静态持续,无链接性
int llama = 0;
...
}
5种变量存储方式
存储描述 | 持续性 | 作用域 | 链接性 | 如何声明 |
自动 | 自动 | 代码块 | 无 | 在代码块中 |
寄存器 | 自动 | 代码块 | 无 | 在代码块中,使用关键字register |
静态,无链接性 | 静态 | 代码块 | 无 | 在代码块中,使用关键字static |
静态,外部链接性 | 静态 | 文件 | 外部 | 不在任何函数内 |
静态,内部链接性 | 静态 | 文件 | 内部 | 不在任何函数内,使用关键字static |
(3) 静态持续性、外部链接性
链接性为外部的变量通常简称为外部变量。 外部变量也称全局变量。
一方面,在每个使用外部变量的文件中,都必须声明它;另一方面,C++有“单定义规则”,该规则指出,变量只能有一次定义。
//external.cpp -- 外部变量
//与support.cpp一起编译
#include<iostream>
using namespace std;
//外部变量
double warming = 0.3; //定义warming
//函数原型
void update(double dt);
void local();
int main() //使用全局变量
{
cout << "Global warming is " << warming << " degrees.\n";
update(0.1); //调用函数更改warming
cout << "Global warming is " << warming << " degrees.\n";
local(); //调用使用局部变量warming的函数
cout << "Global warming is " << warming << " degrees.\n";
cin.get();
return 0;
}
//support.cpp -- 使用外部变量
//和external.cpp一起编译
#include<iostream>
extern double warming; //使用另一个文件中的warming
//函数原型
void update(double dt);
void local();
using std::cout;
void update(double dt) //修改全局变量
{
extern double warming; //可选的重声明
warming += dt; //使用全局变量warming
cout << "Updating global warming to " << warming;
cout << " degrees.\n";
}
void local() //使用局部变量
{
double warming = 0.8; //新变量隐藏了外部变量
cout << "Local warming = " << warming << " degrees.\n";
//用作用域解析运算符访问全局变量
cout << "But global warming = " << ::warming;
cout << " degrees.\n";
}
![](https://i-blog.csdnimg.cn/blog_migrate/480119b7f296abc277edc7e3ba2e5e6d.png)
1. update( )修改了warming,这种修改在随后使用该变量时显现出来了。
2. local( )函数表明,定义与全局变量同名的局部变量后,局部变量将隐藏全局变量。
3. C++比C语言更进一步——它提供了作用域解析运算符(::)。 放在变量名前面时,该运算符表示使用变量的全局版本。
(4) 静态持续性,内部链接性。
将static限定符用于作用域为整个文件的变量时,该变量的链接性将为内部的。
//file1
int errors = 20; //外部声明
...
//file2
static int errors; //仅对file2可用
void froobish()
{
cout << errors; //使用file2中定义的errors
...
}
上述例子没有违反单定义规则,因为关键字static指出标识符errors的链接性为内部,因此并非要提供外部定义。
(5) 静态存储持续性、无链接性
//static.cpp -- 使用一个静态局部变量
#include<iostream>
//常数
const int ArSize = 10;
//函数原型
void strcount(const char * str);
int main()
{
using namespace std;
char input[ArSize];
char next;
cout << "Enter a line:\n";
cin.get(input, ArSize);
while (cin)
{
cin.get(next);
while (next != '\n') //如果next是换行符,则说明cin.get(input, ArSize)读取了整行
cin.get(next); //否则说明行中还有字符没被读取,使用一个循环丢弃余下的字符
strcount(input);
cout << "Enter next line (empty line to quit):\n";
cin.get(input, ArSize); //试图使用get(char *,int)来读取空行将导致cin为false
}
cout << "Bye\n";
cin.get();
return 0;
}
void strcount(const char * str)
{
using namespace std;
static int total = 0; //静态局部变量
int count = 0; //自动局部变量
cout << "\"" << str << "\"contains ";
while (*str++) //直到字符串结尾
count++;
total += count;
cout << count << " characters\n";
cout << total << " characters total\n";
}
1. 由于数组长度为10,因此程序从每行读取的字符数都不超过9个。
2. 每次函数被调用时,自动变量count都被重置为0;然而,静态变量total只在程序运行时被设置为0,以后在两次函数调用之间,其值将保持不变,因此能够记录读取的字符总数。
(6) 函数和链接性
C/C++中所有函数的存储持续性都自动为静态的,即在整个程序执行期间都一直存在。在默认情况下,函数的链接性为外部的,即在文件间共享。实际上,还可以使用关键字static将函数的链接性设置为内部的,使之只能在一个文件中使用。必须同时在原型和函数定义中使用static关键字。
这意味着该函数只在这个文件中可见,还意味着可以在其他文件中定义同名的函数。 和变量一样,在定义静态函数的文件中,静态函数将覆盖外部定义,因此即使在外部定义了同名的函数,该文件仍将使用静态函数。