簡體   English   中英

為什么 operator = 返回 *this?

[英]Why does operator = return *this?

假設我想覆蓋operator =所以我可以做類似的事情

Poly p1;  // an object representing a polynomial
Poly p2;  // another object of the same type    
p2 = p1;  // assigns all the contents of p1 to p2

然后在我對operator =的實現中,我有這樣的東西:

Poly& Poly::operator=(const Poly &source) {
    // Skipping implementation, it already works fine…
    return *this;
}

不要介意實施,它已經可以正常工作了。

我擔心的是當你return *this時會發生什么? 我知道它返回對對象的引用,但會發生這種情況嗎?

p2 = &p1

return *this這樣您就可以編寫普通的復合 C++ =語句,例如:

Poly p1; //an object representing a polynomial
Poly p2;
Poly p2;

// ...

p3 = p2 = p1;  //assigns all the contents of p1 to p2 and then to p3

因為那句話基本上是:

p3.operator=(p2.operator=(p1));

如果p2.operator=(...)沒有return *this你將沒有任何意義傳遞給p3.operator=(...)

p2 = p1p2.operator=(p1)的簡寫。 它只是調用您的operator=函數,該函數返回對p2的引用,然后您將忽略它。 為了清楚起見,我們稱它為assign而不是operator=

Poly& Poly::assign(const Poly &source) {
    .
    .
    .
    return *this;
}

現在代替p2 = p1 ,你會寫

p2.assign(p1);

在這種情況下,調用assign的結果將被忽略,但您不必忽略它。 例如,你可以寫:

p3.assign(p2.assign(p1));

使用operator=而不是assign ,這就變成了

p3 = (p2 = p1);

但由於賦值是右結合的,這也可以寫成

p3 = p2 = p1;

這種能夠同時進行多項賦值的形式最初來自 C,並通過在operator=()中返回*this的約定保留在 C++ 中。

如果您無論如何都不需要鏈式賦值(如其他答案所示),則可能會試圖讓復制賦值運算符返回void 畢竟,鏈式賦值通常難以閱讀和理解,所以不允許它們可能被視為一種改進

但是,一個經常被忽視的方面是void operator=(Poly& const)意味着您的類型將不再滿足CopyAssignable概念,這需要T&返回類型。

不符合CopyAssignable概念的類型不能正式用於某些標准容器操作,例如std::vector::insert ,這意味着以下看似無辜的代碼片段會產生未定義的行為,即使它可能運行得很好美好的:

#include <vector>

struct Poly
{
    void operator=(Poly const&) {} // Poly is not CopyAssignable
};

int main()
{
  std::vector<Poly> v;
  Poly p;
  v.insert(v.begin(), p); // undefined behaviour
}

正如 C++ 標准在 § 17.6.4.8/2.3 中解釋的那樣,它討論了對使用標准庫的程序的約束:

(...) 在以下情況下效果未定義

(...) 對於在實例化模板組件時用作模板參數的類型,如果對該類型的操作未實現適用要求子條款 (...) 的語義

當然,正是由於未定義的行為,編譯器才被允許忽略錯誤並使程序表現得很好,與明顯預期的行為相匹配。 但這不是必需的。

您還應該考慮到您無法預測Poly類型的所有未來用途。 有人可能會編寫一些模板函數,例如:

template <class T>
void f(T const& t)
{
    T t2;
    T t3 = t2 = t;
    // ...
}

此功能將不適用於您的Poly類。

只要不違反此 C++ 約定,您就不會遇到麻煩。

當你返回 *this 時會發生什么?

在您的示例( p2 = p1; )中,什么都沒有。 該方法將p1復制到p2並返回對調用代碼不使用的“this”對象的引用。

p3 = p2 = p1; ,第一個調用是p2 = p1 ,它將p1復制到p2並返回對p2的引用。 然后調用代碼從該對p2的引用復制到p3 (並忽略返回的對p3的引用)。

(順帶一提:您的單元測試是否確保p1 = p1正常工作?很容易忘記這種情況!)

返回對目標對象的引用允許賦值鏈接(級聯),並且類內的重載運算符遵循右關聯(單擊此處了解詳細的運算符重載規則)

Poly a, b, c;
a = b = c;

暫無
暫無

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

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