考虑以下。我有两个导出常量,如下所示:

// somefile.h
extern const double cMyConstDouble;
extern const double cMyConstDouble2;

// somefile.cpp
const double cMyConstDouble = 3.14;
const double cMyConstDouble2 = 2.5*cMyConstDouble;

现在在其他地方引用这些常量来定义两个静态(本地可见)常量:

// someotherfile.cpp
#include "somefile.h"
static const double cAnotherDouble = 1.1*cMyConstDouble;
static const double cAnotherDouble2 = 1.1*cMyConstDouble2;
printf("cAnotherDouble = %g, cAnotherDouble2 = %g\n",
       cAnotherDouble, cAnotherDouble2);

产生以下输出:

cAnotherDouble = 3.454, cAnotherDouble2 = 0

为什么第二个是双0?我正在使用 .NET 2003 C++ 编译器 (13.10.3077)。

有帮助吗?

解决方案

由于cMyConstDouble被声明为extern,编译器不能呈现其值,并且不产生对cMyConstDouble2编译时间初始化。由于cMyConstDouble2未编译时初始化,它的相对的初始化以便cAnotherDouble2是随机的(未定义)。请参见静态初始化惨败更多信息。

其他提示

我不打算动用我的脚趾成的extern这里的问题,但为什么你根本不要将consts在相应的头文件,而忘记了“出口”他们使用的extern?这是consts应该如何在C ++中使用的,为什么它们具有内部链接。

在换句话说:

// someheader.h
const double cMyConstDouble = 3.14;
const double cMyConstDouble2 = 2.5*cMyConstDouble;

和#包括该文件,无论你需要他们。

这是很危险的事情在一个源文件中的一个静态变量取决于在另一个CPP文件中的另一静态变量。检查静态初始化惨败了解更多信息。

如果你改变初始化 cMyConstDouble2 到这里:

const double cMyConstDouble2 = 2.5*3.14;

那么你的程序应该表现正确。其原因是变量

  • 有POD类型
  • 用常量表达式初始化 (1)

在静态初始化时初始化。这些初始化包括

  • 零初始化 全部 具有静态存储持续时间的对象
  • 使用常量表达式初始化的 POD 的初始化

在您显示的变量中,仅 cMyConstDouble 满足在静态初始化时完全初始化的两个条件。然而, cMyConstDouble2 不,因为它的初始值设定项不满足常量表达式的要求。特别是,它包含一个不具有整型类型的变量(此处,它具有浮点类型)。然而,浮点数 文字 允许在算术常量表达式中使用。因此 2.5*3.14 是算术常量表达式。这就是为什么将初始化器更改为该值将需要对其进行静态初始化。


会发生什么 cMyConstDouble2 如果你继续使用非常数表达式?答案是,你不知道。标准允许静态初始化该变量,但不要求这样做。在您的情况下,它是动态初始化的 - 因此在静态初始化时间之后它的值仍然为零。感受如何 复杂的 也就是说,这是一个例子:

inline double fd() { return 1.0; }
extern double d1;
double d2 = d1; // unspecified:
                // may be statically initialized to 0.0 or
                // dynamically initialized to 1.0
double d1 = fd(); // may be initialized statically to 1.0

如果动态初始化没有改变任何其他静态存储变量(满足 你的 代码),并且当静态初始化产生的值与动态初始化产生的值相同时,当所有不需要静态初始化的对象将被动态初始化时(也满足 你的 code) - 然后允许静态初始化变量。上面的代码中两个变量也满足这两个条件 d2d1:

分析 d2

  • = d1 不更改任何其他静态存储变量
  • 当两个 d2d1 动态初始化,然后 d2 将被初始化为 0.0, , 因为 d2 之前已定义 d1, ,以及动态初始化 d2 会抢到的价值 d1 从静态初始化之后的状态开始(其中只有零初始化 d1 发生)。

分析 d1

  • = fd() 不更改任何其他静态存储变量
  • 当两个 d2d1 动态初始化,然后 = fd() 将初始化 d11.0.

所以,编译器可能会初始化 d1 静态地 1.0, ,因为可选静态初始化的两个条件都满足。

  • 如果 编译器决定初始化 d1d2 动态地,那么 d2 将被初始化为 0.0, ,因为它将获取的值 d1 因为它是在零初始化之后。

  • 然而, 如果 编译器决定初始化 d1 静态地和 d2 动态地,那么 d2 将被初始化为 1.0, ,由于动态初始化 d2 将获取完全初始化的值 d1 因为它是在静态初始化之后。

我不确定有什么价值 d2 那时候 d1 d2 不过,是静态初始化的。也就是说,是否 d2 应该抓住 0.0 或者 1.0, ,因为没有为静态初始化定义顺序。


(1) 当考虑具有静态存储持续时间的对象的初始化顺序时,常量表达式也包括算术常量表达式(不仅仅是整型常量表达式)。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top