2014-10-31 174 views
1

這可能是一個微不足道的問題,但我沒有找到滿意的答案,不能真正弄清楚發生了什麼。超載運營商=

假設你有下面的代碼:

#include <iostream> 

class Foo 
{ 
public: 
    void operator=(int) 
    { 
     std::cout << "calling Foo::operator=(int)" << std::endl; 
    } 
}; 

int main() 
{ 
    Foo a, b; 
    a = 10; // it works, of course, no questions here 
    a = b; // why does this work? 
} 

由於我在Foo超載operator=,我希望行a = bmain()吐編譯器錯誤(即a.operator=(b)不應該編譯,因爲有沒有從bint的隱式轉換,後者是輸入類型Foo::operator=(int))。爲什麼分配a = b默默地工作,究竟發生了什麼?編譯器是否會產生一個「默認」operator=(const Foo&),即使在我重載它的情況下?

回答

1

是的,編譯器正在生成一個默認的,平凡的Foo& operator=(const Foo&)。目前只有四種情況的隱含拷貝賦值運算符就不會發生:

  • 你明確告訴它不要(如Foo& operator=(const Foo&) = delete
  • 你宣佈一個自己服用Foo(或Foo&const Foo&
  • 類具有非平凡轉讓的成員(如unique_ptr<T>
  • 你的類有一個定義的移動賦值運算符或構造函數(感謝布賴恩)

更新以下是標準中的一些相關部分。

18年8月12日:

如果類定義不明確聲明拷貝賦值運算符,一個是隱式聲明。如果 類定義聲明移動構造函數或移動賦值運算符,則將隱式聲明的副本 賦值運算符定義爲已刪除;否則,它被定義爲默認

好吧,不過你沒聲明一個拷貝賦值運算符,對不對?還是你?究竟一個拷貝賦值運算符:

17年8月12日:

用戶聲明的拷貝賦值運算符X::operator=X 類恰好與一個參數的非靜態的非模板成員函數類型XX&,const X&,volatile X&const volatile X&。 121 [注意: 重載賦值運算符必須聲明爲只有一個參數;見13.5.3。 - 結束註釋] [注意:可以爲一個類聲明多種形式的複製賦值運算符。 - 注完] [注: 如果一個類X只與X&類型的參數的拷貝賦值運算符,const X 類型的表達式不能分配給類型X

的對象,因此沒有。您作爲賦值運算符聲明爲Foo::operator=(int)的函數不是複製賦值運算符。因此它不符合前一段中不隱式聲明的條件。

所有其它條件在23年8月12日所定義:

類X A拖欠複製/移動賦值運算符被定義爲已刪除如果X具有:

  • 變體構件使用非平凡的相應賦值運算符,並且X是類聯合類,或者是非常量非類類型(或其數組)的非靜態數據成員,或者是
  • 參考類型的非靜態數據成員,或
  • 類型爲M(或其數組)的非靜態數據成員,因爲應用於M的相應分配,因此無法複製/移動,因爲 重載決議(13.3)運算符會導致模糊 或從默認賦值運算符中刪除或不可訪問的函數,或導致直接或虛擬基類B由於過載解析(13.3)而無法複製/移動,因爲 應用於B相應的賦值運算符,會導致模糊或被刪除的功能 或缺省賦值運算符無法訪問,或者
  • 爲移動賦值運算符,非靜態數據成員或類型爲 沒有移動賦值運算符並且不是可以簡單複製的類型的直接基類或任何直接或間接虛擬 基類。
+0

謝謝,看來你知道標準:)你有一秒鐘。數? – vsoftco 2014-10-31 02:05:25

+0

如果存在顯式聲明的移動構造函數或移動賦值運算符,則隱式聲明的複製賦值運算符也將被定義爲刪除。 – Brian 2014-10-31 02:05:31

+0

@布萊恩,謝謝,我知道,對於賦值運算符只是好奇心。似乎有點奇怪,不能爲重載操作符指定「顯式」。這可能很有用,特別是在處理代理對象時。 – vsoftco 2014-10-31 02:08:51