2014-09-26 93 views
1

我看到,在C++中的很多例子中,運算符重載獲取作爲參數的類實例通過引用傳遞,或者如果它返回一個類實例,它也通過引用返回它。爲什麼人們選擇通過引用來傳遞它,而傳遞一個指針/按值的原因是否也有用? 舉例:運算符重載傳遞和返回的參數

Class MyClass 
{ 
public: 
    int m_num; 
    MyClass() { m_num = 1;} 
    const MyClass operator+(const MyClass& mcls) 
    { 
     MyClass temp; 
     temp = m_num + mcls.m_num; 
     return temp; 
    } 
} 

假設我們重載=運算符。

因此,例如我寫的代碼,向運算符+重載函數發送參數而不是通過引用AND ALSO返回一個MyClass的實例,而不是通過引用將工作,但我看到它的很多例子它通過並返回參考,我想知道是否有這個背後的原因,或者它只是某種類型的約定或者可能是偏好?

+0

返回一個const引用並不是真的很好。檢查你應該有的警告。 – chris 2014-09-26 01:51:25

+0

介意解釋你在說什麼更深入?並解決我的主要問題 – 2014-09-26 01:53:53

+0

@ Tugal.44,http://coliru.stacked-crooked.com/a/824e82a5c9e1cf8c – chris 2014-09-26 01:55:16

回答

1

嚴格地說,不需要通過引用或通過常量引用來傳遞:代碼將傳遞值。但是,對於大多數效率低下的操作員來說,因爲按值傳遞需要複製整個對象 - 這是通過引用傳遞時避免的。

返回值也是如此:通常情況下,您應該返回值。但是,這條規則有一個明顯的例外:所有複合賦值操作符都需要通過引用返回,因爲它們返回(*this)

使用指針而不是引用是不可能的,但出於不同的原因:C++要求運算符按類型與特定的簽名兼容;引用與對應類型的值類型兼容,但指針不兼容。如果你定義了一個接受指針的操作符的重載,C++在處理值時不會使用你的操作符。

+0

關於你的第二個賦值操作符。爲什麼我應該回報什麼?不會返回無效足夠好嗎?它只是分配值,爲什麼我應該返回*這個? – 2014-09-26 02:10:01

+0

@ Tugal.44因爲你可以鏈式賦值和複合賦值,例如'a = b = c'或'a = b = C++'等。 – dasblinkenlight 2014-09-26 02:14:10

+0

爲什麼在鏈式賦值中它不能像我們寫一個= b = c所以當做b = c時,b值改變,然後a = b,一個值改變,仍然不明白如何返回一個ref是必要的? – 2014-09-26 02:21:01

1

如果您的實際問題是關於通過const引用傳遞,請參閱Why pass by const reference instead of by value?,否則請繼續閱讀。


您不應該return a reference to a local variable。局部變量超出範圍,留下對垃圾的引用。 C++ operator overloading guidelines指出operator+不應修改任何操作數,並從兩個參數中返回一個新值。

const MyClass operator+(const MyClass& mcls) const 
{ 
    MyClass temp = *this; 
    temp.m_num += mcls.m_num; 
    return temp; 
} 

由於這個原因,重要的是您要返回一份副本。

另一方面,關於operator=,您確實想返回參考,因爲它是copy assignment operator。例如:

MyClass& MyClass::operator=(const MyClass &rhs) { 
    // Check for self-assignment! 
    if (this == &rhs)  // Same object? 
     return *this;  // Yes, so skip assignment, and just return *this. 

    ... // Deallocate, allocate new space, copy values... 

    return *this; 
    } 

你想rhs複製到*this,並返回一個參考:

[...]以支持安全合理的操作鏈接。 (通過返回*該這麼做)。

+0

我很難理解爲什麼返回*這將允許鏈接,dasblinkenlight向我解釋同樣的事情,我已經回覆解釋我不明白,請仔細檢查一下? – 2014-09-26 02:27:10

1

如果你的函數是:

MyClass operator+(const MyClass *mcls) 

那麼代碼a + b不會編譯。你必須寫a + &b這太可怕了。

它是有效的有運營商爲:

MyClass operator+(MyClass mcls) 

此代碼,概念,因爲它是按值傳遞創造了mcls的額外拷貝。如果這個副本實際上可以移出或刪除或優化出來,那麼這是一個很好的風格。否則,const MyClass &版本是一個很好的優化(有時候是過早的!)以避免這種潛在的額外複製。

請注意,它們都應該是const(即函數 - 不是返回值),因爲它們不會修改*thisoperator+被認爲是非會員功能的更好風格

operator+不應該返回參考的原因是人們期望+需要兩個輸入並生成新的輸出。如果代碼是c = a + b;,那麼我們預計a保持不變。你必須在某個地方創建一個新的對象來保存總和,然後返回。當我們按值返回時,這是一個臨時對象,通常編譯器會將其忽略並直接將結果寫入c

operator+=修改*this並返回對*this的引用是正確的。實現operator+的好方法實際上是在第一個操作數上調用operator+=(按值傳遞時)。

+0

爲什麼它被認爲是運營商+成爲非會員功能的更好風格?我同意讓他們常量,忘記。另外爲什麼operator + =應該返回* this?剛纔修改這個成員並做了什麼錯,爲什麼需要從+ =運算符返回? – 2014-09-26 02:14:38

+0

如果你的類沒有成員,你可以同時寫'c = 3 + b;'和'c = a + 3;'如果你的類有'int'的任何轉換構造函數。此外,代碼模塊化和封裝將您的對象的功能與在您的對象上完成的操作分開更好。 – 2014-09-26 02:21:46

+0

您可以在'operator + ='中返回'void',但也可以返回'* this'以允許鏈接。 'func(a + = b);'這意味着'a + = b; FUNC(a)中;'。設計重載操作符的一般想法是使它們儘可能接近內置操作符對內置類型的行爲。然後,使用您的運營商的人沒有任何不愉快的意外。 – 2014-09-26 02:22:24