2015-12-15 58 views
0

有人可以請示例解釋爲什麼在C++中重載逗號,地址,邏輯和和邏輯OR運算符不是一個好習慣嗎?爲什麼逗號,地址 - ,邏輯AND和邏輯OR運算符不應該在C++中重載?

+1

如果您重載了逗號運算符,那麼您就是STL將其C++ STL實現更改爲在適當情況下執行'a,void(),b'的原因。 – chris

+0

我不認爲這個問題應該被視爲'主要基於意見' – Walter

+0

誰說的和什麼時候? –

回答

4

如果有人讀取代碼並看到if(a && b),他/她會怎麼想?
如果a和b是原生類型,如boolint,則每個人都知道它是如何工作的。

如果它們是類對象,大多數人會希望在應用&&之前,該類提供了一個operator bool()或類似的查詢它應該是什麼bool。沒有人會認爲這是一種「幻想」的方式來編寫if(a.myMethod(b)),沒有人願意檢查類定義=>每個人都會誤解和/或混淆狀態的目的是什麼。
tldr,請勿將內置的&&用作無關方法調用的縮寫。

同樣是有效的||,

至於地址運算符,除了讀取混淆問題之外,在編寫代碼時也很常見:指針地址通常可以爲任何類型的變量獲取,並且在執行此操作之前,沒有人會檢查您的類定義。

而且可讀性等等,如果以什麼順序的參數賦值不同:

if(a&&b)正常,如果是falseb甚至沒有檢查了,因爲整個條件只能是假。如果你有像例如。 if(a && func1()) func2();其中返回值func2()很重要,func1()被執行只有如果atrue,並且只有兩者都爲真時纔會執行func2()。超載&&func1()總是執行。取決於它的作用,這可能不是你想要的。

隨着||,這是類似的:如果第一個參數是true,第二個參數通常不會看着了,因爲整個條件爲真,反正。有了過載,參數總是被評估。

正常的逗號運算符a,b有保證ab之前被評估/執行;過載時可以按任何順序。

+1

代碼可讀性是一個問題。但是如果你檢查這個鏈接https://www.securecoding.cert.org/confluence/display/cplusplus/DCL10-CPP.+Do+not+overload+the+ampersand,+comma,+logical+AND+or+logical + OR +操作符,這裏解釋的原因對我來說很難理解。所以,我問了這個現在被低估的問題。 – bornfree

+0

@bornfree我不是在說可讀性。 ...關於您的鏈接,我將補充說明...... – deviantfan

6

潛在的原因是這些運算符的重載版本的行爲與內建版本的行爲不同。這會導致(人類)閱讀/編寫代碼的實質性混亂。

  1. 邏輯運算符&&||的內置版本呈現短路優化:在像a && b一個表達式,a首先計算且僅當trueb還評價;類似地,在a || b,a中首先被評估,並且只有在false,b也被評估。重載運算符&&||沒有短路優化(總是對ab進行評估),也未指定參數計算的順序。

  2. 逗號運算符的內置版本保證參數在它們發生的順序,即,在評價a,ba首先計算然後b。在重載逗號運算符的情況下,這個保證將會丟失(而函數參數機制會發揮作用)。

  3. 地址運算符有內建地址運算符&並且當應用於不完整的類型的對象重載一個之間的潛在的混淆。考慮以下代碼

    struct type;   // forward declaration: type is (as of yet) incomplete 
    
    #include <memory> 
    void foo(type &obj)  // allowed: take object of incomplete type by reference 
    { 
        auto ptr1 = &obj;     // address of obj -- or not? 
        auto ptr2 = std::addressof(obj); // always address of obj  
    } 
    
    // possibly in a different translation unit: 
    struct type 
    { 
        type* operator&() { return nullptr; } 
    }; 
    

    該代碼具有unspecified behaviour:編譯器可以在foo()實現無論是&運營商的版本,但人寫的foo()代碼無法知道這或運營商將被使用。 使用std::addressofptr2相比可以避免此問題,即使type運算符有重載&,該問題也會獲得內建運算符地址的等效值。

+0

根據[CWG1458](http://wg21.link/CWG1458),'運營商&案例現在未指定。 –

+0

謝謝@ T.C。將修改我的答案 – Walter