2017-01-27 158 views
0

比方说,我有一个C以下设置++程序,在全球/命名空间范围(以外的任何块):EXTERN常量,这是声明,这是向前声明

情况1:

a.cpp

extern const int i=5; 

b.cpp

extern const int i; 

有两种方式,在我的脑海里,编译器可以看到这一点。一个是,真正的声明是在b.cpp中,而a.cpp只有一个前向声明和初始化。 (因为我们知道,对于特定的外部常量,在声明时不需要初始化)编译器可能生成的其他可能的可执行文件将包含含有真实声明的a.cpp,并进行初始化,并且可以看到b.cpp中的语句作为前向声明,只需要在那里协助编译器知道我是什么。

编译器如何决定哪个文件负责实际的声明,并因此与我相关的内存分配?如果使用了一个有趣的构造函数,而不是int,那么这可能会有明显的影响。

如何回答这个问题的变化,如果有的话,有:

情况2:

a.cpp

extern const int i; 
extern const int i=5; 

b.cpp

extern const int i; 
+0

你声明它是'extern',你也说你知道它的价值。这似乎是错误的。 – tadman

+0

@tadman我编译时没有任何错误。为什么这是错的?我以为“extern”只是表示标识符名称具有外部链接。这是否也意味着您无法将其初始化为已知值? – Jeff

+0

通常'extern'的意思是“存储在另一个文件中”,链接器负责使其同步。你如何编译所有这些? – tadman

回答

2

初始化程序的存在会立即将声明变为定义(除少数例外,在我们的情况下不相关)。这意味着

extern const int i = 5; 

是你i定义。它定义了i并为其提供了外部链接,即创建了实际的i并使其对其他翻译单元可见(“导出”它)。

同时,

extern const int i; 

是一个非限定声明如果i。它基本上说i在其他地方定义(“进口”它)。

当你因为某些原因需要在C++中的全局const对象的extern适当明确的应用变得至关重要,因为在C++ const对象都默认内部链接

请记住,为使const int对象符合整型常量表达式(ICE)的条件,必须可见ICE初始化程序对该const int对象的声明。

+0

当情况2中两个文件都有一个extern const int语句,并且两个文件都没有附加到a.cpp中发生的初始化时,会发生什么? – Jeff

+0

@Jeff:没什么特别的。你有'i'的多个非定义声明(这是非常好的,你可以有无限数量的)和'i'的单个定义(你可以不超过一个)。所以,everythig是为了。链接器将正确地将所有内容链接在一起。 – AnT

+0

听起来好像你说的情况2,“extern const int i = 5;”正在定义。但是我感到困惑的是情况2中的3个语句中的哪一个负责为我分配内存。即我什么时候第一次成立?另一个问这个问题的方法是,在这两个extern const int i中; a.cpp和b.cpp中的语句,一个是真正的声明,另一个是编译器对我代表的数据类型的提示。哪个是哪个?谢谢! – Jeff