不可预知的布尔比较c ++

时间:2012-03-18 19:37:39

标签: c++ comparison boolean

为什么这段代码会产生看似随机的行为,

std::cout << ( thePointerIsGood = ( NULL != (aPointer = aFunctionThatReturnsAPointer(args)) ) );

当这个做同样事情的多行版本工作正常吗?

aPointer = aFunctionThatReturnsAPointer(args);
thePointerIsGood = (NULL != aPointer);
std::cout << thePointerIsGood;

我正在捕获aPointerthePointerIsGood,因为我稍后会在代码中使用它们。

更新

以上实际上效果很好。但是我能够用这个程序重现一些奇怪的行为,并且我已经标记了错误发生的位置:

// Compiled with:
//   gcc test.cpp -c -o test.o; gcc -lstdc++ test.o -o test

#include <iostream>
#include <cstdlib>

  class
AClass
  { public
    : // Operators ///////////////////////////////////////
      ;  const  bool  operator==  (  const  int  rhs  )  ;
      ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

  }
  ;

  class
AHelperClass
  { public
    : // Functions //////////////////////////////////////////////////////
      ;  static  AClass*  AFunctionThatReturnsAPointer  (  int  arg  )  ;
      ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  }
  ;

  const
  bool
  AClass::
operator==
  (  const  int  rhs  )
  { return (rhs == 222); }

  AClass*
  AHelperClass::
AFunctionThatReturnsAPointer
  (  int  arg  )
  { return ( (arg == 777)
           ? new AClass
           : NULL
           )
           ;
  }

  int
main
  (     int  argc
  ,  char**  argv
  )
  { // Variables //////////////////
    ;  AClass*  aPointer          ;
    ;     bool  thePointerIsGood  ;
    ;     bool  theValueMatches   ;
    ;      int  i                 ;
    ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

    for ( i = 0
        ; i < 10
        ; i++
        )
        { // First a good pointer
          std::cout << ( ( thePointerIsGood = ( NULL != ( aPointer = AHelperClass::AFunctionThatReturnsAPointer(777) ) ) )
                       ? "Y  "
                       : "N  "
                       )  
                    << ( (thePointerIsGood == true)
                       ? "expected    "
                       : "unexpected  " 
                       )
                    ;

          if ( !thePointerIsGood )
             { std::cout << std::endl; }
          else
             { // This is where the error is, thanks to Peter for pointing it out
               std::cout << ( (theValueMatches = ((*aPointer) == 222))
                            ? "Y  "
                            : "N  "
                            )
                         << ( (theValueMatches == true)
                            ? "expected"
                            : "unexpected"
                            )
                         << std::endl
                         ;
             }


          delete aPointer;

          // Now a NULL pointer
          std::cout << ( ( thePointerIsGood = ( NULL != ( aPointer = AHelperClass::AFunctionThatReturnsAPointer(877) ) ) )
                       ? "Y  "
                       : "N  "
                       )  
                    << ( (thePointerIsGood == false)
                       ? "expected    "
                       : "unexpected  " 
                       )
                    ;

          if ( !thePointerIsGood )
             { std::cout << std::endl; }
          else
             { std::cout << ( (theValueMatches = ((*aPointer) == 222))
                            ? "Y  "
                            : "N  "
                            )
                         << ( (theValueMatches == true)
                            ? "expected"
                            : "unexpected"
                            )
                         << std::endl
                         ;
             }


          delete aPointer;
        }

    return 0;
  }

这为我产生了以下输出(一切应该说是预期的)

Y  expected    Y  expected
N  unexpected  
Y  unexpected  Y  expected
N  unexpected  
Y  unexpected  Y  expected
N  unexpected  
Y  unexpected  Y  expected
N  unexpected  
Y  unexpected  Y  expected
N  unexpected  
Y  unexpected  Y  expected
N  unexpected  
Y  unexpected  Y  expected
N  unexpected  
Y  unexpected  Y  expected
N  unexpected  
Y  unexpected  Y  expected
N  unexpected  
Y  unexpected  Y  expected
N  unexpected  

2 个答案:

答案 0 :(得分:1)

我的想法是以下是未定义的行为:

std::cout << ( (theValueMatches = ((*aPointer) == 222))
                            ? "Y  "
                            : "N  "
                            )
                         << ( (theValueMatches == true)
                            ? "expected"
                            : "unexpected"
                            )
                         << std::endl
                         ;

因为theValueMatches在同一个表达式中都被使用并赋值,并且没有定义赋值是在比较true之前还是之后发生的。如果它看起来是不确定的,那确实让我感到惊讶,因为你希望编译器选择一种方法或另一种方法,虽然我发现我的不是 - 我每次从程序得到相同的输出,有很多意想不到的在那里。

答案 1 :(得分:0)

不能保证表达式的评估顺序。如果你有:

x << (a = b) << a;

然后可以在“(a = b)”之前评估“a”