大部分內容在§12.8中描述。第17段定義爲用戶聲明的拷貝賦值運算符什麼罪名:
用戶聲明的拷貝賦值運算符X::operator=
是X
類的非靜態的非模板成員函數X
型,X&
的只有一個參數, const X&
,volatile X&
或const volatile X&
。
第19段定義爲用戶聲明的舉動賦值運算符什麼罪名:
用戶聲明的舉動賦值運算符X::operator=
是X
類的非靜態 非模板成員函數只有一個參數 類型X&&
,const X&&
,volatile X&&
或const volatile X&&
。
因此,它計算爲複製賦值運算符,但不作爲移動賦值運算符。
第18段講述當編譯器生成的拷貝賦值運算符:
如果類定義不明確聲明拷貝賦值操作符 ,一個是隱式聲明。如果類定義聲明瞭 移動構造函數或移動賦值運算符,則隱式聲明的 聲明的複製賦值運算符被定義爲刪除;否則,它被定義爲默認(8.4)。如果 類具有用戶聲明的拷貝構造函數或用戶聲明的析構函數,則不推薦使用後一種情況。
第20段告訴我們,當編譯器生成移動賦值運算符:
如果一個類X的定義不明確宣佈的舉動 賦值運算符,一個將被隱式聲明爲默認如果 且僅當
[...]
- X沒有一個用戶聲明的拷貝賦值運算符,
[...]
由於該類具有用戶聲明的複製賦值運算符,因此編譯器不會生成任何隱式的賦值運算符。
std::is_copy_assignable
和std::is_move_assignable
在表49中被描述爲分別具有與is_assignable<T&,T const&>::value
和is_assignable<T&,T&&>::value
相同的值。該表告訴我們,is_assignable<T,U>::value
是true
時:處理 作爲未計算的操作數(第5章)時
表達declval<T>() = declval<U>()
是良好的。如果在與T
和U
無關的上下文中訪問檢查執行爲 。只考慮分配表達式的直接上下文的有效性。
由於兩個declval<T&>() = declval<T const&>()
和declval<T&>() = declval<T&&>()
都能很好地形成爲階級,它仍然被認爲拷貝分配和移動分配。
正如我在評論中提到的那樣,對於這一切有什麼好奇的是,在存在移動構造函數的情況下,operator=
將正確執行移動,但在技術上不算作移動賦值運算符。如果這個類沒有拷貝構造函數,它就更加奇怪了:它將有一個拷貝賦值操作符,它不會拷貝,而只是移動。
相關討論:http://cpp-next.com/archive/2009/08/want-speed-pass-by-value – mavam 2012-03-17 17:06:28
我在Visual Studio和g ++上都得到編譯器錯誤,如果我有T&operator = (T t)和T&operator =(T && t),因爲它是含糊的 – user929404 2013-05-05 16:06:01
@ user929404:你應該。重點是,你只需要賦值就可以替換複製和移動賦值。 – 2013-05-06 00:33:51