What's the difference between static constexpr and static inline variables in C++17?
用C++ 17得到内联变量。
它们的一个用途是在类中定义常量字段。
那么这两个常量定义之间的区别是什么:
1 2 3 4
| class MyClass {
static constexpr int myFirstVar = 10;
static const inline int mySecondVar = 100;
}; |
当然,constexpr使myFirstVar隐式内联。
在这里,使用constexpr或inline更好的选择是什么?
注:当你不需要警察的时候,那么inline就更容易了。用constexpr你没有选择。
您不必在声明点为mySecondVar指定初始值设定项。初始值设定项也不需要是constexpr本身。
这意味着,如果我们试图这样定义myFirstVar:
1 2 3 4 5
| class MyClass {
static constexpr int myFirstVar;
};
int MyClass::myFirstVar = 1; |
或者像这样:
1 2 3 4 5
| #include <cstdlib>
class MyClass {
static constexpr int myFirstVar = rand();
}; |
这两种方法都是不正确的。constexpr语义有充分的理由要求它。
inline说明符方法允许我们在头本身中包含静态变量定义,而初始值设定项不是constexpr;或者如果初始值设定项相当复杂,则不必在类定义本身中。
这是C++ 17中一个非常有效的标头:
1 2 3 4 5 6 7
| #include <cstdlib>
class MyClass {
static const int mySecondVar;
};
inline const int MyClass::mySecondVar = rand(); |
该标准向我们保证,包括头部的所有翻译单元都将看到相同的变量值,即使在运行时之前我们不知道它是什么。
它主要是一个图书馆作家工具。假设您的库只是头。那么在过去,如果你需要一个这样定义的静态常量,你有什么选择呢?
好吧,您可以在库中附带一个对象文件。它将从只包含常量定义的翻译单元进行编译。现在,库不仅仅是头。
或者您可以改为依赖内联函数。内联变量效果可以通过以下方式实现:
1 2 3 4 5 6 7 8
| class MyClass {
static inline int mySecondVar();
};
inline int MyClass::mySecondVar() {
static const int value = rand();
return value;
} |
但它隐藏在语法墙的后面,并用一个函数调用操作符屏蔽了本质上是常量的内容。
- 这是否意味着具有静态存储持续时间的内联变量对初始化顺序不敏感?
- @如果你不小心的话,奥利弗-西奥夫仍然适用。inline变量唯一保证的是只有一个变量初始化一次。
- 实际上,我之所以问它是因为您的最后一个代码示例意味着不会有任何SIOF。所以内联变量不是这个例子的"等价物",因为我理解"等价物"这个词。也许你可以在答案中提到。
- @奥利弗-我的意思是达到同样的效果。改写的。
- @实际上,我上一个代码示例并没有暗示要考虑它。可以从另一个静态对象的初始化器调用该函数。如果value改为引用一个外部变量,它也会导致siof。
- 别担心,这是图像符号或范例的老问题,总有一些人比作者的意图看得更多!艺术家喜欢它。但对于教学来说,这始终是个问题!我也承认我更喜欢你以前的措辞。
- 你确定吗?我不认为在类之外定义一个EDCOX1 0变量是在C++ 17中有效的,除非它是EDCOX1,3,否则它仍然被弃用,不能初始化。
- @丹妮尔——当然。非常量静态的规则语义仍然适用。内联说明符只确保多个相同的定义保持整个ODR的正确性。
- @我困惑的是,"内联静态数据成员可以在类定义中定义,并且可以指定大括号或相等的初始值设定项。"([class.static.data]p3)。我认为第一个"五月"是"必须"的。
- 你好(专家)。很抱歉,从这个答案中向您表达了歉意,但是(鉴于这个答案涉及同一主题,而且您经常发表深入浅出的答案),您可以对与我对这个问题的答案相关的OP问题提出一些见解,我目前已经耗尽了自己对这个主题的知识,我相信这个悬而未决的问题的形式是"为什么标准会做出这个决定",这是我缺乏知识的推测。
- …特别是,为什么所描述的修改"constexpr说明符暗示来自p0386r0的inline用于变量和函数",指定应用于(7.1.5p1)作为"用constexpr说明符声明的函数或变量隐式地是inline函数或变量…",最终仅限于变量的子集。属于静态数据成员的表;[dcl.constexpr]/1:"用constexpr说明符声明的函数或静态数据成员隐式地是内联函数或变量…"。