在使用未设置的局部变量或在初始化类或结构的成员之前直接访问它们时,捕获一些非常明显的错误是非常好的。在 visual studio 2008 中,您会在编译时收到“使用未初始化的局部变量”警告,并在调试时在访问点收到运行时检查失败。
但是,如果您通过其函数之一访问未初始化结构的成员变量,则不会收到任何警告或断言。显然,最简单的解决方案是不要那样做,但没有人是完美的。
例如:
struct Test
{
float GetMember() const { return member; }
float member;
};
Test test;
float f1 = test.member; // Raises warning, asserts in VS debugger at runtime
float f2 = test.GetMember(); // No problem, just keeps on going
这让我感到惊讶,但它有一定的道理——编译器不能假设在未使用的结构上调用函数是错误的,否则您将如何初始化或构造它?任何更奇特的东西都会很快带来很多其他的复杂性,以至于它不会费心去分类哪些函数可以调用以及何时调用,尤其是作为调试帮助。我知道我可以在类本身内设置自己的断言或错误检查,但这会使一些更简单的结构复杂化。
仍然,它看起来像是在函数调用的上下文中,难道它不知道 GetMember()
内部 member
尚未初始化吗?我假设它不仅依赖于静态编译时推导,考虑到它在执行期间引发的 Run-Time Check Failure #3
,所以根据我目前对它的理解,它似乎是合理的适用相同的检查。这只是此特定编译器/调试器 (Visual Studio 2008) 的限制,还是更多地与 C++ 的工作方式有关?
最佳答案
您可能会注意到警告是关于 test
未初始化的。这就是为什么警告和运行时失败仅适用于该行
float f1 = test.member;
这会导致未定义的行为,并且至少在 Debug模式下,MSVS 会进行一些检查并能够崩溃(在发布中,该错误可能会被隐藏,您最终会在 f1
).
然而,下一行并不直接导致 UB。 f1
不被读取,它的任何数据成员也不被读取(直接)。调用了一个方法,编译器不知道成员函数会在未初始化的对象上产生 UB。该函数可以只在屏幕上打印一些内容而不读取任何成员,这样就可以了。好吧,编译器可以理论上知道,因为它看到了代码,但它并没有深入挖掘。静态代码分析器可能会提醒您注意这个问题。
关于c++ - 在类或结构中使用未设置的成员变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12334685/