在 class 中初始化变量时,我们是否有静态初始化顺序失败

Do we have a static initialisation order fiasco while initialising variables inside the class

我正在尝试将我们的旧代码从 c++98 重构为 c++14。并且需要同时使用较旧的 gcc(c++98) 和较新的 gcc(c++14) 进行编译。这就是我们旧代码的样子(这完全是我们复杂代码的示例。来自这个 class 的静态常量在另一个 class 中使用)。

// BankAccount.h
namespace bank {
class BankAccount {
 public:
    static const unsigned int account_number = 123456789;
    static const double balance = 0.0;
    BankAccount();
    ....
};
}

// BankAccount.cpp
namespace bank {
    BankAccount::BankAccount() {}
    ....
}

看起来从 c++11 开始,只允许在 class 声明中初始化整数和枚举。

问题:通过像上面那样在 class 声明中初始化静态常量变量,是否可以避免静态初始化顺序失败?看起来像上面的代码,我们从来没有观察到这个静态初始化顺序问题,如果我将静态双精度和浮点移动到 .cpp 文件,我应该担心这个问题吗?

(更新:由于问题已更改为 static const 成员)

通过声明它们static const,对于整型变量是安全的。在现代 C++ 中,有 。语言保证您不会 运行 遇到访问未初始化(或零初始化)数值的问题。

对于像 double 这样的浮点数,除非你使用 constexpr,否则它不应该编译。然而,这是一个在 C++98 上不可用的特性。如果没有 constexpr,你会得到这样的编译错误:

// gcc
example.cpp:6:25: error: ‘constexpr’ needed for in-class initialization of static data member ‘const double bank::BankAccount::balance’ of non-integral type [-fpermissive]
    6 |     static const double balance = 0.0;
      |                         ^~~~~~~

或仅具有非标准功能:

// clang with -Wall -std=c++98
example.cpp:6:25: warning: in-class initializer for static data member of type 'const double' is a GNU extension [-Wgnu-static-float-init]
    static const double balance = 0.0;

(没有声明它们的旧答案 const,但它们是非常量)

你确定这个例子吗?我认为它不会编译(在 C++98 和现代 C++ 中)。除非你将初始化移出 class 定义,否则你会得到类似的东西:

// gcc
example.cpp:5:30: error: ISO C++ forbids in-class initialization of non-const static member ‘bank::BankAccount::account_number’
    5 |     static unsigned long int account_number = 123456789;
      |                              ^~~~~~~~~~~~~~
example.cpp:6:19: error: ‘constexpr’ needed for in-class initialization of static data member ‘double bank::BankAccount::balance’ of non-integral type [-fpermissive]
    6 |     static double balance = 0.0;
      |                   ^~~~~~~
// clang
example.cpp:5:30: error: non-const static data member must be initialized out of line
    static unsigned long int account_number = 123456789;
                             ^                ~~~~~~~~~
example.cpp:6:19: error: non-const static data member must be initialized out of line
    static double balance = 0.0;
                  ^         ~~~

如果你把它移出去,那么你可能会以静态初始化顺序失败告终。这些值将从零初始化开始,然后取决于链接器何时执行真正的初始化代码。

不过,如果可以将变量声明为常量,那将是安全的。