为什么静态内联变量需要“内联”?

时间:2017-10-22 12:27:39

标签: c++ inline c++17

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

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

要求inline规范背后的理由是什么?为什么不简单地允许程序员编写

    static int i = 8;
在课堂上

1 个答案:

答案 0 :(得分:12)

没有inline,它只是明确声明为声明。正如[class.static.data]/2

中所述
  

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

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

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

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

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

n可以用作常量表达式来定义bar的范围,并且它不被视为使用odr。现在我们把它写成constexpr 1 ,但是上面的内容仍然有效。但可能n必须使用odr的情况(想象它的地址,或绑定它的引用等)。它们可能并不多,也可能不常见,但是某些API有疯狂的要求,最终会导致这种情况的发生。

const int foo::n;

出现在某个翻译单元中。

现在,如果static inline int i = 8;突然隐含inline,则上面的定义(即现有代码库中的定义)将违反了odr。现在以前格式良好的代码是不正确的。因此,最好只允许显式 inline在此处生效,因为只有新代码才会实际拥有它。

<子> 1 有人可能认为static constexpr变量可能有相同的问题(但它们是隐式内联的)。但是IIRC的原始措辞允许这种改变而不会破坏现有的代码。除了名字之外,它基本上已经“内联”了。