我在复制和查找错误原因方面遇到了很大的问题。出现似乎是完全随机的,所以我怀疑某处有一个未初始化的变量。但后来我找到了这段代码:
CMyClass obj; // A
obj.DoStuff();
if ( somebool )
{
CMyClass obj; // B
obj.DoStuff();
}
obj.DoOtherStuff();
似乎DoOtherStuff()要么在“B”上完成,要么B.DoStuff()有时实际上在A上工作 - 即实际上在第一个obj上调用了DoStuff()。
这会发生吗?我不认为我收到了编译器警告(我现在修改了代码,希望它可能有所帮助)。似乎非常可能这段实际代码是我想要找到的bug的地方,但当然还有其他原因我还没有发现。
答案 0 :(得分:5)
编写的代码应该有效。第一次拨打DoStuff()
和最后一次拨打DoOtherStuff()
只能发送到A
。
DoStuff()
块中对if(somebool) { }
的调用只能发送到B
。
来自standard:
3.3.2本地范围
- 块(6.3)中声明的名称是该块的本地名称。它的潜在范围始于其声明(3.3.1)和 结束于其声明区域的末尾。
醇>
和
3.3.7名称隐藏
- 可以通过嵌套声明性区域或派生类(10.2)中相同名称的显式声明来隐藏名称。
醇>
话虽如此,也许这不是该代码的作者的意图。如果变量具有相同的名称,则意图可能只有该变量的一个实例,并且在循环内创建的B
实例是错误的。你是否经历过逻辑,看看第二个实例是否有意义?
答案 1 :(得分:3)
除非obj.DoStuff()
对某个全局对象进行更改,否则Valentin指出它应该全部包含在if语句的范围内
答案 2 :(得分:2)
与全局变量同名的局部变量会隐藏该块内的全局变量。但是,全局范围运算符(::)可用于告诉编译器您的全局版本
CMyClass obj; // A
obj.DoStuff();
if ( somebool )
{
CMyClass obj; // B
obj.DoStuff(); //does on B
::obj.DoStuff(); //does on A
}
obj.DoOtherStuff(); //this will call A because B is destroyed
因此当局部变量B超出范围时会被销毁。拥有与全局变量同名的局部变量通常是一个麻烦的召唤,所以尽量避免使用。
答案 3 :(得分:2)
如果您使用GCC,您可以(并且 - 在我看来 - 应该)使用-Wshadow,它会在例如您的示例中的情况下发出警告,这通常会带来非常微妙的错误。
然而,就像许多其他人已经说过的那样,你粘贴的代码是正确的,做你期望的,并且不是未定义的行为。
答案 4 :(得分:1)
不,这不可能发生。
编译器保证在退出if作用域时正确销毁B对象,而在alive时它会作用于自己的地址空间。
错误发生在其他地方。
答案 5 :(得分:0)
您的代码可能在语法上是正确的,但这些方法有何用处?例如,堆栈溢出可能会导致您正在观察的怪异行为。