何时在C ++中使用extern


398

我正在阅读“在C ++中思考”,它刚刚引入了extern声明。例如:

extern int x;
extern float y;

我想我理解了含义(没有定义的声明),但是我想知道它何时证明有用。

有人可以提供例子吗?


1
我不得不extern在多个场合提供定义。当仅定义另一个源文件中的表时,Microsoft工具会产生缺少符号的链接错误。问题是,该表是const由C ++编译器将其升级到static翻译单元中的。参见,例如,ariatab.cppkalynatab.cpp
jww

2
而且我认为Nik的答案是正确的,因为他是似乎唯一回答过C ++问题的人。其他所有人似乎都对C问题感到迷惑。
jww

Answers:


519

当您有全局变量时,这很有用。您可以在标头中声明全局变量的存在,以便每个包含标头的源文件都知道它,但是只需要在一个源文件中“定义”一次即可。

为了澄清,用extern int x;告诉编译器类型的对象int称为x存在的地方。知道它的存在不是编译器的工作,它只需要知道类型和名称,就知道如何使用它。编译完所有源文件后,链接器将解析x对它在已编译源文件之一中找到的一个定义的所有引用。为了使它起作用,x变量的定义需要具有所谓的“外部链接”,这基本上意味着它需要在函数外部(通常称为“文件范围”)之外声明且没有static关键字。

标头:

#ifndef HEADER_H
#define HEADER_H

// any source file that includes this will be able to use "global_x"
extern int global_x;

void print_global_x();

#endif

来源1:

#include "header.h"

// since global_x still needs to be defined somewhere,
// we define it (for example) in this source file
int global_x;

int main()
{
    //set global_x here:
    global_x = 5;

    print_global_x();
}

来源2:

#include <iostream>
#include "header.h"

void print_global_x()
{
    //print global_x here:
    std::cout << global_x << std::endl;
}

15
谢谢。因此,如果我在没有extern关键字的头文件中声明了全局变量,则包含头的源文件看不到它吗?
Aslan986

23
您不应该在标头中声明全局变量,因为那样,当2个文件包含相同的标头文件时,它就不会链接(链接器将发出有关“重复符号”的错误)
kuba 2012年

63
@ Aslan986:不,更糟的事情发生了。每个包含标头的源文件都有其自己的变量,因此每个源文件将独立编译,但是链接器会抱怨,因为两个源文件将具有相同的全局标识符。
dreamlax 2012年

7
当您不使用单词“ extern”时,则该变量存在。当您使用“外部”时,它是“嘿其他地方有这个变种”。很抱歉不回答是定义还是声明,因为我总是对这两个感到困惑。
古巴2012年

3
@CCJ:包含保护仅适用于包含它的源文件。它停止将同一标头包含在同一源文件中两次(以防其他标头也包含它,以此类推)。因此,即使有了包含保护,包含头的每个源文件仍将具有自己的定义。
dreamlax18年

172

当您在几个模块之间共享变量时,此功能很有用。您可以在一个模块中定义它,而在其他模块中使用extern。

例如:

在file1.cpp中:

int global_int = 1;

在file2.cpp中:

extern int global_int;
//in some function
cout << "global_int = " << global_int;

39
这个答案比公认的答案更正确,因为它不使用头文件,并且清楚地表明仅在几个模块之间共享时才有用。对于较大的应用程序,最好使用ConfigManager类。
扎克

1
global_int如果我要在某些名称空间部分的file2.cpp中使用它,那么在涉及到名称空间时,是否存在陷阱,是否在全局名称空间中?即namespace XYZ{ void foo(){ ::global_int++ } };
jxramos

8
@Zac:另一方面,由于没有在标头中声明全局变量,因此无意中使确定它的实际定义位置变得更加困难。通常,如果您看到在中声明了全局变量abc.h,则很有可能在中定义它abc.cpp。好的IDE总是有帮助的,但是组织良好的代码总是更好的解决方案。
dreamlax

extern在file2.cpp中没有,global_int包括之后仍然可以访问。为什么我需要它?
TomSawyer

62

关于链接的一切。

先前的答案对给出了很好的解释extern

但我想补充一点。

您问的externC ++,而不是C,我不知道为什么没有答案提及C ++ extern附带的情况const

在C ++中,const默认情况下,变量具有内部链接(与C不同)。

因此,这种情况将导致链接错误

来源1:

const int global = 255; //wrong way to make a definition of global const variable in C++

来源2:

extern const int global; //declaration

它需要像这样:

来源1:

extern const int global = 255; //a definition of global const variable in C++

来源2:

extern const int global; //declaration

2
为什么在定义部分不包含“ extern”的情况下在c ++中运行时是错误的?
首席变速官

1
我似乎在VIsual Studio和Visual Micro中没有遇到该链接错误。我想念什么?
Craig.Feied

1
@ lartist93 @ C​​raig.Feied我相信您可能需要再次仔细检查。即使在编译器未通知链接错误的情况下,您是否可以检查两个源中的两个对象是否相同但没有extern定义?您可以通过打印global源2 的值来实现
。– Trevor

3
确认,在MSVS 2018有一个链接错误,如果extern在被省略const int global = 255;
EVG

13

当您想要一个全局变量时,这很有用。您在某个源文件中定义了全局变量,并在头文件中将它们声明为extern,以便任何包含该头文件的文件都将看到相同的全局变量。


无论如何,这听起来不是很糟糕,我会把它们放到单例类中……或者一个返回本地静态值的函数中……
RzR 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.