【问题标题】:Static const data member defined in another file在另一个文件中定义的静态 const 数据成员
【发布时间】:2017-03-02 12:27:49
【问题描述】:

我正在为 C++11 开发一个静态分析器。类的静态 const 成员和链接之间存在交互,我不确定它是否已定义。仅当未定义此构造时,我的静态分析器才会发出警告。

这个例子是这样的:

在文件 f1.cpp 中:

struct Foo {
    static const int x = 2;
};

int main(void) {
    return *&Foo::x;
}

在文件 f2.cpp 中:

struct Foo {
    static int x;
};

int Foo::x;

使用clang++ -std=c++11 -Weverything f1.cpp f2.cpp 编译和链接的两个文件不会导致警告并生成返回0 的二进制文件。使用g++ -std=c++11 -Wall -Wextra -pedantic f1.cpp f2.cpp 编译时相同的文件不会导致警告并返回2。

我的直觉是这个程序定义不明确但不需要警告,因为:

  • 两个名称 Foo::x 在 N3376[basic.link]p5: 之后都有外部链接

    另外,一个成员函数,静态数据成员,[...] 具有用于链接目的的 typedef 名称 (7.1.3),如果类的名称具有外部链接,则具有外部链接 链接。

  • 但它们违反了 N3376[basic.link]p10 要求:

    在所有类型调整之后(在此期间 typedefs (7.1.3) 被它们的定义替换),类型 引用给定变量或函数的所有声明指定的应相同 [...] 违反此类型标识规则不需要诊断。

要 100% 确定这一点,需要对这些“所有类型的调整”进行定义,但在 C++11 标准中似乎无处可寻。有没有,上面的推理正确吗?

【问题讨论】:

  • 见§basic.def.odr/p5 特别是5.1: There can be more than one definition of a class type ... each definition of D shall consist of the same sequence of tokens; and

标签: c++ c++11 language-lawyer


【解决方案1】:

这是违反 ODR 的。 Foo 类型在每个文件中都有不同的声明。

一个定义说 x 是用外部链接声明的(可以是任何东西,在链接时确定),另一个定义是它是一个值为 2 的编译时常量。

【讨论】:

  • N3376[class.static.data]p1 不允许这样做吗? > 静态数据成员不是类的子对象的一部分。
  • @Szm:Foo::x 存在 ODR 违规,现在您可能认为class Foo 可以,只有静态部分有问题,但无论如何程序格式错误。跨度>
  • @szm 子对象在这里无关紧要。我已经扩展了答案。
  • @Jarod42:在 N3376[class.static.data]p2 之后:“静态数据成员在其类定义中的声明不是定义 [...]”所以 file1.cpp 不包含Foo::x 和 file2.cpp 的定义包含 Foo::x 的一个定义。我不明白为什么 Foo::x 在这里违反了 ODR。
猜你喜欢
  • 2011-03-02
  • 2012-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多