C++ 为什么非成员静态constexpr变量不是隐式内联的?

C++ 为什么非成员静态constexpr变量不是隐式内联的?,c++,static,inline,c++17,C++,Static,Inline,C++17,在C++17中,我们得到了内联变量,我假设全局constexpr变量是隐式内联的。 但显然,这只适用于静态成员变量 这背后的逻辑/技术限制是什么 资料来源: 声明为constexpr的静态成员变量(但不是命名空间范围变量)隐式为内联变量 constexpr静态数据成员隐式inline的原因是为了解决C++中的一个常见问题:在定义类作用域常量时,之前必须在一个转换单元中发出定义,以免使用ODR变量: // foo.h struct foo { static constexpr int kA

在C++17中,我们得到了内联变量,我假设全局constexpr变量是隐式内联的。 但显然,这只适用于静态成员变量

这背后的逻辑/技术限制是什么

资料来源:

声明为constexpr的静态成员变量(但不是命名空间范围变量)隐式为内联变量


constexpr
静态数据成员隐式
inline
的原因是为了解决C++中的一个常见问题:在定义类作用域常量时,之前必须在一个转换单元中发出定义,以免使用ODR变量:

// foo.h
struct foo {
    static constexpr int kAnswer = 42;
};

// foo.cpp
// a linker error will occur if this definition is omitted before C++17
#include "foo.h"
constexpr int foo::kAnswer;

// main.cpp
#include "foo.h"
#include <vector>
int main() {
    std::vector<int> bar;
    bar.push_back(foo::kAnswer);  // ODR-use of 42
}
//foo.h
结构foo{
静态constexpr int kAnswer=42;
};
//foo.cpp
//如果在C++17之前省略此定义,则会发生链接器错误
#包括“foo.h”
constexpr int foo::kAnswer;
//main.cpp
#包括“foo.h”
#包括
int main(){
向量条;
bar.push_back(foo::kAnswer);//ODR使用42
}
在这种情况下,我们通常只关心常量的值,而不关心它的地址;编译器可以方便地为常数合成一个唯一的位置,以防它真的被ODR使用,但我们不关心该位置在哪里

因此,C++17更改了规则,因此不再需要越界定义。为此,它使
foo::kAnswer
的声明成为一个内联定义,这样它就可以在多个翻译单元中出现而不会发生冲突,就像内联函数一样


对于命名空间范围
constexpr
变量(隐式
静态
,因此具有内部链接,除非声明
外部
),没有类似问题。每个翻译单元都有自己的副本<当前指定的代码>内联,对这些变量没有影响。改变现有的行为会破坏现有的程序。

这里的要点是
constexpr int x=1在C++14中具有内部链接

如果在不更改内部链接部分的情况下将其隐式内联,则更改将无效,因为内部链接意味着无法在其他转换单元中定义它。它损害了可教性,因为我们想要
inline constexpr int x=1默认情况下获取外部链接(毕竟,内联的整个要点是允许在多个转换单元中定义相同的变量)

如果将其隐式内联到外部链接,则会破坏现有代码:

// TU1
constexpr int x = 1;

// TU2
constexpr int x = 2;

这个完全有效的C++14将成为ODR冲突。

inline
对于具有内部链接的变量没有多大意义OK,但是为什么全局constexpr静态可以内联呢?这有什么意义?@Brian,您可以在头文件中声明静态constexpr基元类型,而无需在.cpp文件中声明它们。它们不是ODR使用的。你的例子说只在C++17之后,但那不是真的。它适用于C++11和14。@AdvSphere仅当它们是命名空间范围的。不是类成员。@Brian,我不确定你说的话中是否遗漏了什么,但我有一段代码,在声明类的头文件中,在类范围内定义了
static constexpr double value{1.5}。标题包含在多个翻译单元中,可以正常工作。我们谈论的是不同的事情吗?@AdvSphere只有在您没有意外使用ODR成员的情况下才有效,例如通过调用
std::vector::push_back(value)
。命名空间范围内的
inline constepr
变量是否具有隐式外部链接?在此上下文中,constexpr意味着const。const表示静态链接(在名称空间范围内)。或者这是一个特殊的额外规则?在“内部链接打开”下:内联变量被显式地从列表中排除(“非内联(自C++17)const限定变量(包括constepr),这些变量未声明为extern,并且以前未声明为具有外部链接”)。所以他们被排除在内部链接之外->他们有外部链接?