这个问题与随后提出的问题密切相关这里。
Stroustrup 在here 描述了定义类内常量的方法。
当我遵循 Stroustrup 的方法时,我看到了预期的结果。 但是,在 Visual Studio 2010 中,调试器无法解析该类范围内的
static const
类成员。
这就是我的意思:
#include <iostream>
class Foo {
public:
static const int A = 50;
char arr[A];
void showA();
};
void Foo::showA() {
std::cout << "showA = " << A << "\n";
}
int main() {
Foo f;
f.showA();
}
当调试器位于 showA() 中时,“watch”窗口报告:
Error: Symbol "Foo::A" not found
我想强调的是,程序确实按预期运行,即输出是:
showA = 50
程序返回 0。
其他人可以使用 Visual Studio 2010 重现此问题吗? 这是调试器中的错误吗?
您可以在全局命名空间范围内为静态数据成员添加定义:
const int Foo::A;
添加静态数据成员定义(这不是必需的但允许的)似乎可以解决您的问题。
我在VS2010的调试版本上对此进行了测试,当定义存在时,
A
的值正确显示在调试窗口中(而当定义丢失时,会报告错误消息,与您提到的一致)。
这不是一个错误。编译器可以(并且几乎总是会)优化静态常量基本类型。编译器只是将
A
的值内联到已编译的指令中,而不是为 A
分配存储空间。
因为
A
没有存储在任何地方,它没有地址,所以调试器无法查看它。
Visual C++ 错误地提供了弱定义(本答案中提供的证据):
类定义中静态数据成员的声明不是定义,并且可能是除 cv 限定之外的不完整类型
。静态数据成员的定义应出现在包含该成员的类定义的命名空间范围中。在命名空间范围的定义中,静态数据成员的名称应使用void
运算符通过其类名进行限定。::
根据标准中的另一条规则,如果成员不是 odr-used,则不需要定义。
无论 Visual C++ 是否错误地提供了显式定义或弱定义,都没有什么区别。 如果该成员不是 odr-used,链接器将看不到任何对它的引用,并将删除它,从而使调试器对它是否曾经存在感到困惑。 通过 Microsoft 链接器,您可以使用
/OPT:NOREF
来抑制此优化。
最终,这不是您想要在生产代码中执行的操作,因为您的应用程序中会残留标准库中的各种残留内容。 但对于调试期间临时使用来说,这是一个合理的设置。