关于C++ extern的简单总结

Posted fu3638

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于C++ extern的简单总结相关的知识,希望对你有一定的参考价值。

extern可以实现多文件共享同一个变量、const常量、函数。
下面结合几个例子来讲一下extern的相关性质(下述皆为多文件编译):

例1:

//file1.cpp
#include<iostream>
using namespace std;

extern int count;

int main(){

    cout<<count<<endl;
    return 0;

}


//file2.cpp

int count=3;

...

将两个文件一起编译,则输出会是3,因为file1使用了在file2中定义的全局变量count,全局变量也叫外部变量,具有外部链接性,意思就是可以被外部文件引用。

注意,当使用extern声明变量时,要求被声明的变量只能在一个文件中被定义,比如再有个file3里面也定义了一个名为count的全局变量,然后跟file1、file2一起编译,那编译器就会报错,因为不知道要引用哪个count,这也被称为单独定义规则。

总而言之,在多文件程序中,可以在一个文件(且只能在一个文件)中定义一个外部变量。使用该变量的其他文件必须使用extern来声明他。(摘自C++ Primer Plus)

例2:

//file1.cpp
#include<iostream>
using namespace std;

void f(int x){

    if(x>3) return;
    extern int count;
    count++;
    cout<<count<<endl;
    f(x+1);
}

int main(){
    f(1);
    return 0;
}

//file2.cpp

int count=1;
...

上述例子中,file1和file2一起编译,运行后的输出是:

2

3

4

因为file1使用extern声明的count实际上就是file2中的count(同一个存储地址),file1只是声明要引用file2中的count,而不是重新定义一个count,所以即使递归调用函数也不会影响count保留上一次的值。这一点跟用static定义一个内部变量很像,不同的是static定义的内部变量只能初始化一次,而extern声明的变量不能初始化。

例3:

//file1.cpp
#include<iostream>
using namespace std;

extern const int x;

int main(){
    cout<<x<<endl;
    return 0;
}

//file2.cpp
extern const int x=5;
...

上述例子中,file1和file2一起编译,运行后的输出是5。显然file1通过extern声明引用了在file2中的const常量x。

但是为什么file1和file2都要加extern? 要如何实现多个文件共享一个const常量呢?

因为const声明的常量它的链接性是内部的,默认是不能被其他文件用extern引用的。也就是说例1中说的单定义规则对它并不适用,所以即使在多个文件中定义同名的const常量,也不会有问题。

可以使用extern来覆盖其默认的内部链接性,就像file2中做得那样,并且只能在一个文件中被初始化。


例4:

//file1.cpp
#include<iostream>
using namespace std;

extern void f(int x);

int main(){
    f(2);
    return 0;
}

//file2.cpp
#include<iostream>
using namespace std;

void f(int x){
    cout<<x<<endl;
}
    
...

上述例子的输出为2,file1中利用extern引用了file2中的extern。函数的链接性和常规变量类似,故例1中讲的性质对函数都适用,不再赘述。

若想函数只在文件内部可见,可使用static关键字将函数的链接性设置为内部的。

以上是关于关于C++ extern的简单总结的主要内容,如果未能解决你的问题,请参考以下文章

C++总结keywords to the class

c++基础篇c++快速入门(extern c专题)

(C++) 如何将 stl 列表声明为 extern?

在混合 C 和 C++ 代码编程中捕获异常后对象不会被破坏

C++编译过的C代码为什么要用extern C

extern关键字用法总结(顺带初始化和赋值的区别)