extern const,哪个是声明,哪个是前向声明
Extern const, which is the declaration and which is the forward declaration
假设我在 C++ 程序中有以下设置,在 global/namespace 范围内(在任何块之外):
情况一:
a.cpp
extern const int i=5;
b.cpp
extern const int i;
在我看来,编译器可以通过两种方式看到这一点。一是 i 的真正声明在 b.cpp 中,而 a.cpp 只有前向声明和初始化。 (因为我们知道对于特定的 extern 常量,不需要在声明时进行初始化)编译器可以生成的其他可能的可执行文件将包含 a.cpp 包含真实声明、初始化和 [=36 中的语句=] 被视为前向声明,只需要在那里帮助编译器知道我是什么。
编译器如何决定哪个文件负责实际声明,并因此决定与 i 关联的内存分配?如果使用具有有趣构造函数的类型而不是 int,这可能会产生表面上可观察到的效果。
如果有的话,这个问题的答案是如何改变的:
情况二:
a.cpp
extern const int i;
extern const int i=5;
b.cpp
extern const int i;
初始化器的存在立即将声明变成定义(除了少数例外,与我们的上下文无关)。这意味着
extern const int i = 5;
是您的i
的定义。它定义 i
并为其提供外部链接,即创建实际的 i
并使其对其他翻译单元可见("exports")。
同时,
extern const int i;
如果 i
, 是一个 non-defining 声明。它基本上说 i
在别处定义("imports")。
当您出于某种原因需要 C++ 中的全局 const
对象时,extern
的正确显式应用变得至关重要,因为在 C++ 中 const
对象具有 默认内部链接。
请记住,为了使 const int
对象符合积分常量表达式 (ICE) 的条件,具有 ICE 初始值设定项的 const int
对象的声明必须可见。
假设我在 C++ 程序中有以下设置,在 global/namespace 范围内(在任何块之外):
情况一:
a.cpp
extern const int i=5;
b.cpp
extern const int i;
在我看来,编译器可以通过两种方式看到这一点。一是 i 的真正声明在 b.cpp 中,而 a.cpp 只有前向声明和初始化。 (因为我们知道对于特定的 extern 常量,不需要在声明时进行初始化)编译器可以生成的其他可能的可执行文件将包含 a.cpp 包含真实声明、初始化和 [=36 中的语句=] 被视为前向声明,只需要在那里帮助编译器知道我是什么。
编译器如何决定哪个文件负责实际声明,并因此决定与 i 关联的内存分配?如果使用具有有趣构造函数的类型而不是 int,这可能会产生表面上可观察到的效果。
如果有的话,这个问题的答案是如何改变的:
情况二:
a.cpp
extern const int i;
extern const int i=5;
b.cpp
extern const int i;
初始化器的存在立即将声明变成定义(除了少数例外,与我们的上下文无关)。这意味着
extern const int i = 5;
是您的i
的定义。它定义 i
并为其提供外部链接,即创建实际的 i
并使其对其他翻译单元可见("exports")。
同时,
extern const int i;
如果 i
, 是一个 non-defining 声明。它基本上说 i
在别处定义("imports")。
当您出于某种原因需要 C++ 中的全局 const
对象时,extern
的正确显式应用变得至关重要,因为在 C++ 中 const
对象具有 默认内部链接。
请记住,为了使 const int
对象符合积分常量表达式 (ICE) 的条件,具有 ICE 初始值设定项的 const int
对象的声明必须可见。