【问题标题】:Extern and const in C++C++ 中的外部和常量
【发布时间】:2014-09-22 08:52:17
【问题描述】:

我看过几篇关于这个问题的帖子,但没有一篇能很好地解释我的担忧,所以我会尝试在这里解释我的理解,如果我错了,请纠正我。

假设我有一个带有以下声明的头文件:

//definitions.h
extern const float fallingTime; 

现在,我有两个要使用此声明的源文件。

//source1.cpp
#include "definitions.h"
const float fallingTime = 0.5f;
//use fallingTime 

//source2.cpp
#include "definitions.h"
//just use fallingTime (no definition required)

这就是我所做的;但现在,假设以另一种方式继续。

//definitions.h
const float fallingTime = 0.5f; //Note that I don't use extern now

//source1.cpp
#include "definitions.h"
//just use fallingTime (no definition required)

//source2.cpp
#include "definitions.h"
//just use fallingTime (no definition required)

正如我从阅读几个资料中得出的结论,前一种方法的优点是它节省了内存和编译时间,因为内存分配只发生一次(在 source1.cpp 中的定义中),而在后一种方法中,内存分配发生在包含 definitions.h(source1.cpp 和 source2.cpp)的每个源文件中。对吗?

最后,同时使用 extern 和定义常量意味着什么?会等同于前一种方法吗?

//definitions.h
extern const float fallingTime = 0.5f;

【问题讨论】:

  • 检查 const 的外部和内部链接。
  • 它也依赖于编译器..
  • 与任何答案都不相关,但您为什么使用float?与double 相比,唯一的性能提升将来自 RAM 芯片,而不是 CPU 本身(可能使用 80 位浮点)。顺便说一句,0.5 可以不典型地用浮点数精确表示,因为它是二元有理数。
  • 它依赖于编译器,但第二种方法很可能会在持续传播期间看到fallingTime 被优化掉。

标签: c++ constants extern


【解决方案1】:

const float fallingTime = 0.5f; 在标头中定义时,翻译单元可能会或可能不会将值存储在二进制文件的数据部分中。

如果翻译单元中没有代码获取地址或对fallingTime 的引用,则编译器根本没有理由在数据段中分配值。编译器很可能会用它的值替换 fallingTime 的用法,因为它的定义在编译时在每个翻译单元中都是可用的。

使用extern const,生成的代码必须从内存中加载fallingTime 的值,因为它的定义在编译时在任何其他翻译单元中都不可用,但定义fallingTime 值的翻译单元除外。

【讨论】:

  • 那么,您是说在这种情况下,两种方式在内存和编译时间上是等效的?
  • @FrancisMoy 为您更新了答案。
  • 好吧,我的推理错了。那么,如果第二种方法可能更优化(从编译时间/内存的角度来看),为什么通常建议将第一种方法作为最佳实践?将 extern 用于常量的优点是什么?第二种方法的唯一问题是@TomTanner 解释的问题?
  • @FrancisMoy 为什么通常建议第一种方法作为最佳实践? - 在哪里? 第二种方法的唯一问题是 TomTanner 解释的问题 - 我认为他的回答不准确。
  • @FrancisMoy 好吧,const 在全局和命名空间范围级别意味着内部链接,即static constconst 相同,但不是extern const。这种行为是在 C++ 中专门实现的,以避免对常量使用宏,stackoverflow.com/a/998457/412080... 同意你的观点。
【解决方案2】:

后一个问题是,在 C++11 之前的 C++ 下,取决于您的编译器,您可能会收到链接时间错误,因为没有fallingTime 的地址。语言要求您在一个翻译单元中对其进行实例化,特别是 gcc 对此非常严格。

【讨论】:

  • 对不起,我不明白。 “后者”是指extern和定义一起使用吗?
  • @FrancisMoy “假设以其他方式继续”中的代码
  • 所以,通过 extern(外部链接),我们强制为常量分配一个内存地址,如果获取引用或常量的地址,这可能是必要的,对吧?
  • 没有。唯一强制使用内存地址的方法是在源文件中定义它(或多或少。有一些微妙之处)
  • 全局和命名空间范围const对象自C++98以来有内部链接(隐式static应用),声明就是定义,不需要其他定义。除非明确标记为extern。你的答案不正确。
猜你喜欢
  • 2012-03-28
  • 2011-02-04
  • 2018-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-18
  • 2010-10-26
  • 2014-07-02
相关资源
最近更新 更多