8

这个问题与此处随后提出的问题密切相关。

Stroustrup 在这里描述了定义类内常量的方法。

当我遵循 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 重现这个吗?这是调试器中的错误吗?

4

3 回答 3

7

您可以在全局命名空间范围内为您的静态数据成员添加定义:

const int Foo::A;

添加静态数据成员定义,这不是必需但允许的,似乎可以解决您的问题。

我在使用 VS2010 的调试版本上对此进行了测试,A当定义存在时, 的值正确显示在调试窗口中(而当定义丢失时会报告错误消息,与您提到的一致)。

于 2013-05-03T19:06:25.340 回答
3

这不是错误。编译器可以(并且几乎总是会)优化静态常量基本类型。A编译器只是将 的值内联A到已编译的指令中,而不是为 分配存储空间。

因为A它没有存储在任何地方,它没有地址,所以调试器无法查看它。

于 2013-05-03T19:04:29.780 回答
2

尽管标准中有明确的语言, Visual C++ 错误地基于类内的声明提供了一个弱定义(此答案中提供的证据) :

静态数据成员在其类定义中的声明不是定义,并且可能是 cv-qualified 以外的不完整类型void。静态数据成员的定义应出现在包含该成员的类定义的命名空间范围内。在命名空间范围的定义中,静态数据成员的名称应使用运算符由其类名限定::

根据标准中的另一条规则,如果成员不是odr-used,则不需要定义。

然而,Visual C++ 错误地提供了显式定义还是弱定义并没有区别。如果该成员不是odr-used,则链接器将看不到对它的任何引用并将其删除,从而使调试器对它是否曾经存在感到困惑。使用 Microsoft 链接器,您可以使用/OPT:NOREF.

不过,最终这不是您想要在生产代码中做的事情,因为您的应用程序中会留下标准库中的各种残留物。但是对于调试期间的临时使用,这是一个合理的设置。

于 2013-05-06T19:49:59.743 回答