C++中的内部连接和外部连接
(必须吐槽一句,博客园的审批对于这样的细节问题似乎有点不屑,恰恰这样的问题才是记录在这里常翻阅的,否则项目代码上git,放这里干什么)
首先,由global变量引出我们今天的问题:
C++中global变量是全局可见的,可以在不同的compilation unit(编译单元)中使用。
如下两个文件:
1.cpp
int a = 1;
2.cpp
#include<iostream>
extern int a;
int main()
{
std::cout<<a<<std::endl;//输出1
}
________________________________________________________________________
提醒一下,这里的int a 是全局变量,属于静态变量,存储在静态数据段。
又static关键字,通常用在一个局部变量,使之变为静态变量。如果用在一个global变量上,当然,这个global变量还是静态的。只是,它变为了局部可见:在自己所在的compilation unit可见。
1.cpp
static int a = 1;
2.cpp
#include<iostream>
extern int a;
int main()
{
std::cout<<a<<std::endl; //编译可通过,出现链接错误!
}
编译通过,但链接错误的原因是,我们在编译阶段,因为extern int a这句话告诉编译器,a在某个地方定义,它是有效的。但是,在链接时,链接器找不到int a的定义。
问题出在1.cpp中的static关键字上,它使得全局变量a的由外部连接的属性变为了内部连接:只在自己的compilation unit可见,链接器不对其他compalition unit可见。所以,我们上面的程序中,链接器找不到int a。
记住,全局变量是静态变量,static global也是静态变量,但是,它们的链接属性不一样。
————————————————————————————————————————————————————————————
具有内部连接的关键字还有const。
static 和 extern不能对同一个变量同时声明。
但const和extern不是同一存储类别,可以同时用在同一个变量的声明。所以,我们可以用使用extern关键字修改const的连接属性
1.cpp
const int a = 21;
2.cpp
#include<iostream>
extern const int a;
int main()
{
std::cout<<a<<std::endl; //编译可通过,出现链接错误!
}
修改为
1.cpp
extern const int a = 21;
2.cpp
#include<iostream>
extern const int a;//注意,这里的const不可以略去
int main()
{
std::cout<<a<<std::endl; //输出21
}
————————————————————————————————————————————————————————————
在C++中具有内部连接属性的有:static的全局变量,枚举类型的定义,类的定义,内联函数的定义,union的定义,名字空间中const定义。
(最后,提醒一个容易犯错的地方:在函数体外定义:const char* p = "xx";p是外部连接的,因为const没有修饰p)