2012-03-18 140 views
1

爲什麼這個代碼產生看似隨意的行爲,不可預知的布爾比較C++

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 
+0

我建議你不要做,在一個行多任務。但問題很有趣。 – heinrich5991 2012-03-18 19:41:16

+1

'args'是否以任何方式引用'aPointer'和/或'thePointerIsGood'? 'aFunctionThatReturnsAPointer'? – ruakh 2012-03-18 19:43:48

+2

請讓我們看看實際的代碼 – Philipp 2012-03-18 19:43:56

回答

1

我的想法是,下面是未定義的行爲:

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

由於theValueMatches既使用並且在相同的表達賦予,並且它不是否定義第e分配發生在與true比較之前或之後。它讓我感到驚訝,如果它看起來不確定,因爲你希望編譯器選擇一種或另一種方法,儘管我觀察到我不是 - 我每次都會從程序中獲得相同的輸出,但有不少意想不到的在那裏。

+0

http://stackoverflow.com/questions/2129230/cout-order-of-call-to-functions-it-prints的答案似乎同意這一點。 – uesp 2012-03-18 20:44:38

+0

這對我有意義。我現在看到它是如何被模糊解釋的。這個問題根本不是我職位的第一部分,而是這個部分。我認爲我不會像你剛纔說的那樣思考這個陳述。謝謝!我的代碼每次都可以正常工作,但我真的很好奇爲什麼這種方式不起作用。 – jnfjnjtj 2012-03-18 20:46:37

0

表達式的評估順序無法保證。如果您有:

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

然後「a」可以被之前「(A = B)」評估