簡體   English   中英

C ++邏輯運算符返回值

[英]C++ logical operators return value

這是我用C ++編寫的一些代碼。 調用了addAVP()函數

dMessage.addAVP(AVP_DESTINATION_HOST, peer->getDestinationHost() || peer->getHost());

它有兩個版本:一個在第二個參數中重載到addAVP(int, char*) ,另一個在addAVP(int, int) 我發現我使用的C ++編譯器稱為addAVP(int, int)版本,這不是我想要的版本,因為getDestinationHost()getHost()都返回char*

盡管如此|| 運算符定義為返回布爾值,因此我可以看到我的錯誤在哪里。 布爾以某種方式計為整數,並且可以干凈地編譯並調用第二個addAVP()

最近,我使用了許多動態類型化的語言,即lisp,上面的代碼是正確的,可以編寫而無需擔心。 顯然,上面的C ++代碼顯然是一個大錯誤,但仍然存在一些問題:

  1. 我是否應該在C ++中使用這種快捷方式,即使用||運算符的返回值。 這個編譯器依賴嗎?

  2. 想象一下,我真的不得不寫一個漂亮a || b a || b語法,可以在C ++中干凈地完成嗎? 通過編寫運算符重新定義? 不損失性能?

作為我最初的請求的后續行動,或者是我自己對2 :-)的回答,我一直在考慮使用類來封裝(邪惡的)原始指針:

class char_ptr_w {
  const char* wrapped_;
public:
  char_ptr_w(const char* wrapped) : wrapped_(wrapped) {}
  char_ptr_w(char_ptr_w const& orig) {  wrapped_=orig.wrapped(); }
  ~char_ptr_w() {}
  inline const char* wrapped() const { return wrapped_; }
};

inline char_ptr_w operator||(char_ptr_w &lhs, char_ptr_w& rhs) {
  if (lhs.wrapped() != NULL)
    return char_ptr_w(lhs.wrapped());
  else
    return char_ptr_w(rhs.wrapped());
};

然后我可以使用:

char_ptr_w a(getDestinationHost());
char_ptr_w b(getHost());

addAVP(AVP_DESTINATION_HOST, a || b);

其中, addAVP將為char_ptr_w重載。 根據我的測試,這產生至多相同的匯編代碼三元a?b:c的解決方案,特別是因為NRVO優化操作,這 ,在大多數編譯器,調用拷貝構造函數(盡管你包括在內)。

自然,在這個特定示例中,我同意三元解決方案是最好的。 我也同意,重新定義操作員是要小心的事情,並不總是有益的。 但是,從C ++的角度來看,上述解決方案在概念上有什么問題嗎?

重載邏輯運算符在C ++中是合法的,但前提是一個或兩個參數均為類類型,無論如何這是一個非常糟糕的主意。 重載的邏輯運算符不會短路 ,因此這可能導致程序中其他地方的有效代碼明顯崩潰。

return p && p->q;  // this can't possibly dereference a null pointer... can it?

如您所見,布爾確實是一個整數。 編譯器正在為您的占用空間選擇正確的功能。 如果您想保留相似的語法,可以嘗試

char*gdh=0;
dMessage.addAVP(AVP\_DESTINATION\_HOST, 
                (gdh=peer->getDestinationHost()) ? gdh : peer->getHost());

我強烈建議您不要重新定義運算符。 從維護的角度來看,這很可能會使以后的開發人員感到困惑。

為什么在兩個char指針上使用“或”運算符?

我假設peer-> getDestinationHost()或peer-> getHost()可以返回NULL,而您正在嘗試使用返回有效字符串的對吧?

在這種情況下,您需要單獨執行以下操作:


char *host = peer->getDestinationHost();
if(host == NULL)
  host = peer->getHost();
dMessage.addAVP(AVP\_DESTINATION\_HOST, host);

將布爾值傳遞給需要char *的函數沒有任何意義。

在C ++中|| 返回布爾值,而不是其操作數之一。 與語言作斗爭通常是個壞主意。

1)我應該在C ++中使用這種快捷方式嗎,即使用||運算符的返回值。 這個編譯器依賴嗎?

它與編譯器無關,但與||的功能不同 運算符使用JavaScript等語言or通用Lisp。 它將第一個操作數強制為布爾值,如果該操作數為true,則返回true。 如果第一個操作數為false,則對第二個操作數求值並強制為布爾值,然后返回此布爾值。

所以它的作用與( peer->getDestinationHost() != 0 ) || ( peer->getHost() != 0 ) ( peer->getDestinationHost() != 0 ) || ( peer->getHost() != 0 ) 此行為不依賴於編譯器。

2)想象一下,我真的必須寫一個漂亮的||。 b語法,可以在C ++中干凈地完成嗎? 通過編寫運算符重新定義? 不損失性能?

由於您使用的是指向chars的指針,因此您不能重載運算符(重載需要一個類類型的形式參數,並且您有兩個指針)。 等效的C ++語句將第一個值存儲在一個臨時變量中,然后使用?:三元運算符,或者您可以內聯地編寫它,但要使用兩次評估第一個表達式的代價。

您可以改為執行以下操作:

dMessage.addAVP(AVP_DESTINATION_HOST,(peer-> getDestinationHost())?peer-> getDestinationHost():peer-> getHost());

這不像||那樣整潔。 但靠近它。

好吧,您對代碼的問題所在是正確的: b將返回一個布爾值,該布爾值將轉換為int(對於false,為0,對於true為!= 0)。

至於您的問題:

  1. 我不確定返回值是否實際上是在標准中定義的,但是我不會使用||的返回值。 除了布爾值之外,其他任何情況下都沒有(因為這還不清楚)。

  2. 我會用? 運算符。 語法為:(表達式)? (如果為true,則執行):(如果為false,則執行)。 所以在您的情況下,我會寫:(peer-> getDestinationHost()=!NULL)嗎? peer-> getDestinationHost():peer-> getHost()。 當然,這將兩次調用getDestinationHost(),這可能不是所希望的。 如果不是這樣,您將必須保存getDestinationHost()的返回值,在這種情況下,我會忘記使其簡短而整潔,而在函數調用之外僅使用普通的舊“ if”即可。 這是使它保持工作狀態,高效且最重要的是可讀性的最佳方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM