为什么静态内联变量需要"inline"?

Why is "inline" required on static inline variables?

本文关键字:inline 变量 静态 为什么      更新时间:2023-10-16

C++17允许静态成员变量定义如下:

class X {
public:
static inline int i = 8;
};

要求inline规范的基本原理是什么?为什么不简单地允许程序员编写

static int i = 8;

在课堂上?

在没有inline的情况下,它被明确地声明为一个声明。按照[class.static.data]/2 中的规定

类中非内联静态数据成员的声明定义不是定义,可能是不完整类型比cv无效。不是的静态数据成员的定义类定义中内联定义的应出现在命名空间中包含成员的类定义的范围。

基本原理很可能是保持遗留代码的完整性和有效性。回想一下,我们可以从大约永远开始初始化类定义本身中的积分常数。但是odr使用它们仍然需要在某些翻译单元中进行类外定义。

因此,在现有的代码库中,使这些变量隐式内联可能会产生问题。当添加核心语言功能时,委员会总是考虑向后兼容性。

例如,考虑这个有效的C++03类定义:

struct foo {
static const int n = 3;
double bar[n];
};

n可以用作常数表达式来定义bar的范围,它不被认为是odr用途。现在我们把它写成constexpr1,但是上面的仍然有效。但是,如果必须使用n,则可能存在的情况(想象它的地址被占用,或者绑定到它的引用,等等)。它们可能不多,也可能不常见,但某些API有疯狂的需求,最终将需要这种

const int foo::n;

出现在某个翻译单元中。

现在,如果static inline int i = 8;突然隐式地变成inline,那么上面的定义(即在现有的代码库中)将是odr冲突。现在,以前格式良好的代码是格式错误的。因此,最好只允许显式inline在这里生效,因为只有新代码才会真正拥有它


1有人可能会认为static constexpr变量可能有同样的问题(但它们是隐式内联的)。但IIRC最初的措辞允许这一改变,而不会破坏现有的规范。除了名字之外,它基本上已经"内联"了