【问题标题】:What's the difference between static constexpr and static inline variables in C++17?C ++ 17中的静态constexpr和静态内联变量有什么区别?
【发布时间】:2017-12-24 07:09:20
【问题描述】:

在 C++17 中,我们得到内联变量。

它们的用途之一是在类中定义常量字段。

那么这两个常量定义有什么区别:

class MyClass {
    static constexpr int myFirstVar = 10;
    static const inline int mySecondVar = 100;
};

当然constexpr 使myFirstVar 隐式内联。

这里有什么更好的选择,使用constexprinline

注意:当您不需要 const 时,inline 会更容易。使用constexpr,您没有选择余地。

【问题讨论】:

  • 简单:尽你所能constexpr

标签: c++ c++17 constexpr


【解决方案1】:

您不必在声明时为mySecondVar 指定初始化程序。初始化器本身也不需要是constexpr

这意味着如果我们尝试像这样定义myFirstVar

class MyClass {
    static constexpr int myFirstVar;
};

int MyClass::myFirstVar = 1;

或者像这样:

#include <cstdlib>

class MyClass {
    static constexpr int myFirstVar = rand();
};

无论哪种方式,它都是不正确的。 constexpr 语义需要它并且有充分的理由。

inline 说明符方法允许我们在标头本身中包含一个静态变量定义,而初始值设定项不是constexpr;或者如果初始化程序相当复杂,它不必在类定义本身中。

所以这是 C++17 中一个完全有效的标头:

#include <cstdlib>

class MyClass {
    static const int mySecondVar;
};

inline const int MyClass::mySecondVar = rand();

该标准向我们保证,所有包含标头的翻译单元都会看到相同的变量值,即使我们在运行时才知道它是什么。

它主要是一个库编写器工具。假设您的库只是标题。那么在过去,如果您需要这样定义的静态常量,您有什么选择?

好吧,您可以在库中附带一个目标文件。它将从只包含常量定义的翻译单元编译。现在该库不再是仅标头了。

或者您可以改用内联函数。内联变量效果可以通过以下方式实现:

class MyClass {
    static inline int mySecondVar();
};

inline int MyClass::mySecondVar() {
  static const int value = rand();
  return value;
}

但它隐藏在语法墙后面,并用函数调用运算符掩盖了本质上是常量的内容。

【讨论】:

  • 是否意味着具有静态存储时长的内联变量对初始化顺序不敏感?
  • @Oliv - 如果您不小心,SIOF 仍然适用。 inline 变量唯一保证的是只有一个变量被初始化一次
  • @DanielH - 非常确定。非常量静态的常规语义仍然适用。内联说明符仅确保多个相同的定义保持整个 ODR 正确。
  • @StoryTeller 我感到困惑的部分是“一个内联静态数据成员可以在类定义中定义并且可以指定一个brace-or-equal-initializer。 ” ([class.static.data]p3)。我认为第一个“可能”是“必须”。
  • ... 特别是,为什么所描述的修改 constexpr 说明符意味着变量和函数的 inline 来自 P0386R0,指定应用到 (7.1.5p1) as “使用 constexpr 说明符声明的函数 或变量 隐含地是 inline 函数或变量 ...”,最终限制为作为静态数据成员的变量子集; [dcl.constexpr]/1:"一个函数或用 constexpr 说明符声明的静态数据成员隐含地是一个内联函数或变量...".
猜你喜欢
  • 2014-06-25
  • 1970-01-01
  • 2010-09-25
  • 1970-01-01
  • 2011-05-27
  • 1970-01-01
  • 2011-01-14
  • 2011-07-05
相关资源
最近更新 更多