代码之家  ›  专栏  ›  技术社区  ›  Srekel

这会导致未定义的行为吗?

  •  2
  • Srekel  · 技术社区  · 16 年前

    我在复制和查找错误原因方面遇到了很大的问题。这种情况似乎完全是随机的,所以我怀疑某个地方有一个未初始化的变量。但后来我发现了这段代码:

    CMyClass obj; // A
    obj.DoStuff();
    
    if ( somebool )
    {
        CMyClass obj; // B
        obj.DoStuff();
    }
    
    obj.DoOtherStuff();
    

    似乎dootherstuff()要么在“b”上完成,要么b.dostuff()有时实际上在a上工作,即i dostuff()实际上在第一个obj上被调用。

    这会发生吗?我想我没有收到编译器警告(我已经修复了代码,希望它能有所帮助)。看起来 非常 很可能这段实际的代码就是我试图找到的bug所在的地方,但当然还有其他的原因我还没有发现。

    6 回复  |  直到 16 年前
        1
  •  5
  •   James Eichele Bernard Igiri    16 年前

    写的代码应该有效。第一次呼叫 DoStuff() 最后一次呼叫 DoOtherStuff() 只能发送到 A .

    呼唤 doSuffor() 里面 if(somebool) { } 块只能发送到 B .

    standard :

    3.3.2本地范围

    1. 块(6.3)中声明的名称是该块的本地名称。其潜在范围始于其声明点(3.3.1),以及 结束于其声明性区域的结尾。

    还有:

    3.3.7名称隐藏

    1. 在嵌套的声明性区域或派生类(10.2)中,可以通过该名称的显式声明隐藏名称。

    也就是说,也许这不是 打算 由代码的作者。如果变量具有相同的名称,那么目的可能是只拥有该变量的一个实例,并且 在循环中创建的实例是错误的。你有没有仔细研究一下逻辑,看看第二个实例是否有意义?

        2
  •  3
  •   ChrisF    16 年前

    除非 obj.DoStuff() 对某个全局对象进行更改,然后正如Valentin所指出的,它应该都是独立的,包含在if语句的范围内。

        3
  •  2
  •   TStamper    16 年前

    与全局变量同名的局部变量隐藏该块中的全局变量。但是,全局范围运算符(::)可以用来告诉编译器您指的是全局版本。

    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超出范围时,它就会被销毁。拥有与全局变量同名的局部变量通常是一种麻烦,所以尽量避免。

        4
  •  2
  •   Andreas Bonini    16 年前

    如果您使用gcc,您可以(并且在我看来应该)使用-wshadow,它会在一些情况下发出警告,例如您的示例中的一个,这通常会出现非常细微的错误。

    然而,正如许多人已经说过的,您粘贴的代码是正确的,执行您所期望的,并且不是未定义的行为。

        5
  •  1
  •   Valentin Galea    16 年前

    不,不可能。

    编译器保证在退出if作用域时正确地销毁b对象,而在活动时,它将作用于自己的地址空间。

    错误在其他地方。

        6
  •  0
  •   dontcallmi    16 年前

    您的代码在语法上可能是正确的,但是这些方法做什么呢?例如,堆栈溢出可能会导致您观察到的可怕行为。