【问题标题】:Extern const, which is the declaration and which is the forward declarationextern const,这是声明,也是前向声明
【发布时间】:2017-01-27 19:24:02
【问题描述】:

假设我在 C++ 程序中有以下设置,在全局/命名空间范围内(在任何块之外):

情况1:

a.cpp

extern const int i=5;

b.cpp

extern const int i;

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

编译器如何决定哪个文件负责实际声明,以及与 i 相关的内存分配?如果使用具有有趣构造函数的类型而不是 int,这可能会产生明显的影响。

这个问题的答案如何改变(如果有的话):

情况2:

a.cpp

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

b.cpp

extern const int i;

【问题讨论】:

  • 您在声明它extern 并且您还说您知道它的价值。这似乎是错误的。
  • @tadman 编译时没有任何错误。为什么这是错误的?我认为“extern”只是意味着标识符名称具有外部链接。是不是也意味着不能将其初始化为已知值?
  • 通常extern 表示“存储在另一个文件中”,链接器负责使其同步。你是如何编译所有这些的?
  • @tadman 为简单起见,我们可以假设我在某处有一个打印 i 的 main 函数,仅此而已。
  • @tadman: extern 并不一定意味着“存储在另一个文件中”。 extern 表示“具有外部链接”。当 extern 应用于 定义 时,它具有“导出”语义(即“其他文件可以访问”)。当extern 应用于非定义声明 时,它具有“导入”语义(即“存储在另一个文件中”)。

标签: c++ constants extern linkage


【解决方案1】:

初始化器的存在立即将声明变成定义(除了少数例外,与我们的上下文无关)。这意味着

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 对象的声明必须是可见的。

【讨论】:

  • 当两个文件都有一个 extern const int 语句,并且两个文件都没有附加到随后在 a.cpp 中发生的初始化时,情况 2 会发生什么?
  • @Jeff:没什么特别的。你有多个i 的非定义声明(这很好,你可以有无限数量的)和一个i 的定义(你不能超过一个)。所以,一切都井然有序。链接器会将所有内容正确链接在一起。
  • 听起来你是说在情况 2 中,“extern const int i=5;”正在定义。但我感到困惑的是,情况 2 中的 3 个语句中的哪一个负责为 i 分配内存。 IE。我什么时候第一次出现?问这个问题的另一种方法是,在两个 extern const int i; a.cpp 和 b.cpp 中的语句,一个是真正的声明,另一个是向编译器提示 i 代表什么类型的数据。哪个是哪个?谢谢!
  • @Jeff:i定义就是这样:它是为i 分配内存。 extern const int i; 只是编译器的“提醒”。 extern const int i = 5;i 的实际内存分配。
  • 听起来你在告诉我,在非定义声明中,它们总是前向声明,没有一个是特殊的。内存仅在定义时分配。因此,即使编译器在您请求未初始化的值时经常给您垃圾,但这实际上并不意味着应该已经分配了内存。这只是编译器编写者对未定义行为期间发生的情况的选择。
猜你喜欢
  • 1970-01-01
  • 2017-03-08
  • 1970-01-01
  • 2019-03-23
  • 1970-01-01
  • 2011-04-30
  • 1970-01-01
相关资源
最近更新 更多