C ++静态const成员定义

时间:2017-02-01 14:45:27

标签: c++

我知道静态const成员必须具有out-ouf-class定义,因为它们使用起来很多。但问题是,即使没有成员定义,我的程序也会编译并运行得很好。

让我们从C ++ FAQ中看一下这个例子:

class AE
{
public:
    static const int c6 = 7;
    static const int c7 = 31;
};
const int AE::c7;   // definition

void f()
{
    const int* p1 = &AE::c6;    // error: c6 not an lvalue
    const int* p2 = &AE::c7;    // ok

    cout << *p1 << endl;
}

int main()
{
    f();

    const int* p1 = &AE::c6; 
    std::cout << p1 << "\n";

    return 0;
}


//RESULT:
// 7
// 00007FF735E7ACE8

我没有看到任何错误。我使用Visual Studio 2015,这段代码编译并运行得很好。

我的问题:这是针对msvc的,还是有一些我不知道的语言变化?

更新:这不是重复,正如我在一开始所说:我确实理解这假设是如何工作的,我不明白为什么它不能正常工作。

3 个答案:

答案 0 :(得分:4)

该程序明确违反了您在问题中所述的一个定义规则。但是在这种情况下,该标准不需要诊断。这在3.2定义规则[basic.def.odr]§4(强调我的)

中是明确的
  

每个程序都应该包含每个非内联函数或变量使用的变量的一个定义   在该计划中; 无需诊断

和1.4实施合规性[intro.compliance]§2.3说:

  

如果程序包含违反不需要诊断的规则,则为本国际   标准对该程序的实施没有要求。

这意味着gcc对该程序的阻塞是正确的,因为违反了一条规则。但是当MSVC接受它作为编译器扩展(*)而没有警告时,这不是一个错误,因为标准在这里没有要求

我们处于编译时未定义的行为,名为格式错误的程序,无需诊断。编译器实现可以自由地执行它想要的任务:

  • 拒绝该计划
  • 自动修复错误并生成代码,就像定义存在一样(对于当前情况)
  • 删除有问题的行[s]如果有意义并使程序可编辑 - 即使生成的内容不是程序员所期望的那样
  • 将其编译为以运行时错误结束的程序
  • [添加您想到的任何内容,但我从未见过编译器能够击中我的猫......]

(*)更确切地说,如果记录,它是编译器扩展。不幸的是,我目前没有MSVC编译器完整的文档,所以我不能说它是否是文档化的,是一个符合标准的扩展,或者不是,只是嗯...一个可能的程序执行

这是OP代码的一个细微变化,证明编译器确实提供了一个定义:

#include <iostream>

class AE {
    // ...
public:
    static const int c6 = 7;
    static const int c7 = 31;
};
const int AE::c7;   // definition

int main()
{
    const int* p1 = &AE::c6;    // error: c6 not an lvalue
    const int* p2 = &AE::c7;    // ok
    // ...
    std::cout << *p1 << "(" << p1 << ") - " << *p2 << "(" << p2 << ")" << std::endl;
    return 0;
}

输出是(使用旧的MSVC 2008,调试模式以避免尽可能多的优化):

7(00DF7800) - 31(00DF7804)

是预期值和连续地址

使用相同的代码,Clang 3.4在链接时抱怨(如预期的那样)

undefined reference to `AE::c6'

答案 1 :(得分:1)

恰好发生,你的编译器已经应用了一些优化,这意味着在这种情况下它并不要求你遵循一个定义规则。

但是,C ++标准仍然要求您这样做,因此您的程序具有未定义的行为。该标准不要求编译器在您违反此特定规则时告诉您,因此选择不这样做。实际上,它必须付出额外的努力才能发现问题。

答案 2 :(得分:0)

  

C ++标准说([basic.def.odr] 3.2第2段)“变量   其名称显示为潜在评估的表达式是使用odr   除非它是满足出现要求的对象   在常量表达式(5.19)和左值到右值的转换中   (4.1)立即申请。“

Read this for further information