关于静态数据成员类内初始化的混淆 我正在阅读lippman的C++入门书。303他们给出: class Account { private: static constexpr int period = 30; double daily_tbl[period]; }

关于静态数据成员类内初始化的混淆 我正在阅读lippman的C++入门书。303他们给出: class Account { private: static constexpr int period = 30; double daily_tbl[period]; },c++,C++,如果仅在编译器可以替换成员值的上下文中使用该成员,则不需要单独定义初始化的const或constexpr static。但是,如果我们在不能替换值的上下文中使用该成员,则必须对该成员进行定义 此外: 例如,如果我们将Account::period传递给一个接受常量int&的函数,那么必须定义period 因此,我尝试添加这样一个函数: class Account { private: static constexpr int period = 30; double daily_tbl[p

如果仅在编译器可以替换成员值的上下文中使用该成员,则不需要单独定义初始化的const或constexpr static。但是,如果我们在不能替换值的上下文中使用该成员,则必须对该成员进行定义

此外:

例如,如果我们将Account::period传递给一个接受常量int&的函数,那么必须定义period

因此,我尝试添加这样一个函数:

class Account {
private:
  static constexpr int period = 30;
  double daily_tbl[period];

  void foo(const int &i) { ; }
  void bar() { foo(period); } //no error?
};

在这里我添加了一个函数,它接受常量int&。我也没有为period变量添加任何定义。但我仍然没有得到错误,因为他们说我应该得到。为什么不呢?

违反此规则不需要诊断。所以行为实际上是未定义的


我认为不需要对其进行诊断的原因是,该诊断将由链接器给出。当编译器优化访问时(就像在本例中可能发生的那样),链接器再也不会注意到任何错误。如果仍然注意到这个错误,就需要在链接器中对整个程序进行分析,以便它能够访问原始的未优化源代码表示。这会增加编译时间,并需要高级链接器和编译器。

规则在哪里定义?能否请您在回答中详细说明?也许9.4.2/4是相关的?“在程序中使用odr(3.2)的静态数据成员应该只有一个定义;不需要诊断。”@alok我认为原因在于诊断将由链接器给出。当编译器优化访问时(就像在他的例子中可能发生的那样),链接器再也不会注意到任何错误。如果仍然注意到此错误,则需要进行整个程序分析,这会增加编译时间并需要高级链接器和编译器。也许这样问太傻了,但为什么要将
period
classify的常量引用作为编译器无法替换值的上下文?这是否类似于获取类内初始化静态成员的地址的原理,这意味着对象必须放置在某个内存位置,而不仅仅是优化输出?为什么呢