回答
沒有實現,這不是不確定的行爲,這將是實現定義的行爲,它將取決於如何實施移動分配。
與此相關的是LWG issue 2468: Self-move-assignment of library types,請注意這是一個活躍的問題,並且沒有官方提議,因此應該將其視爲指示性的而不是明確的,但它確實指出了涉及標準庫的部分並指出他們目前有衝突。它說:
假設我們寫
vector<string> v{"a", "b", "c", "d"}; v = move(v);
應該是什麼v的狀態是什麼?該標準沒有說什麼 具體關於自我移動分配。標準的幾個 部分中有相關的文字,目前尚不清楚如何協調它們。
[...]
這不是從文本如何把這些碎片拼湊起來清楚,因爲目前還不清楚哪一個優先。也許17.6.4.9 [res.on.arguments]獲勝(它強加了MoveAssignable需求中未提及的隱式前置條件,因此v = move(v)未定義),或者可能是23.2.1 [container.requirements.general ](它明確地給出了Container :: operator =的額外保證,超出了一般庫函數的保證範圍,所以v = move(v)是沒有操作的),或者別的什麼。
在我檢查的現有實現上,爲了什麼是值得的,v = move(v)似乎清除了向量;它沒有保持矢量不變,也沒有導致崩潰。
,並提出:
非正式:改變MoveAssignable和集裝箱需求表(和提舉分配任何其他要求的表,如果有的話),使之明確得到x =移動(x)是定義的行爲,它使x處於有效但未指定的狀態。這可能不是標準今天所說的,但它可能是我們的意圖,它與我們告訴用戶以及實際執行的內容是一致的。
注意,對於內置類型這基本上是一個拷貝,我們可以從C++ 14標準牽伸部看到5.17
[expr.ass]:
在簡單賦值(= ),表達式的值會替換左邊的 操作數引用的對象的值。
這比上課的情況,其中5.17
說不同:
如果左操作數是類類型,該類應完整。由複製/移動賦值運算符(12.8,13.5.3)定義 對類的對象的賦值。
請注意,clang有self move warning。
我不會在LWG 2468中提出這個建議,這只是問題提交者的建議,並不一定反映LWG的觀點。根據所寫的標準,我會爭辯說[res.on.arguments]中的限制爲標準庫類型提供了自動分配UB。 –
@ T.C。這是公平的一點,我應該更加小心我的措辭。我更仔細地更新了措辭。 –
「只是一個建議」是輕描淡寫的; Matt Austern是最受尊敬的LWG成員之一。我不是100%確定他是否仍然是LWG的主席,但他已經很長時間了。 – MSalters
它將調用X::operator = (X&&)
,所以它是由管理此情況下(因爲它是爲X::operator = (const X&)
完成)
如果我使用copy-swap成語,我定義了一個統一的賦值運算符(通過值而不是const ref捕獲),該怎麼辦?在這種情況下,我無法檢查運營商實施內部的自我分配。 – becko
所要做的就是致電X::operator=(X&&)
(具有左值限定「*this
」)。
在原始類型上,std::move
幾乎沒有興趣,並且根本不與=
進行交互。所以這隻適用於類類型的對象。
現在,對於std
(或由其模板之一生成)中的類型,對象將傾向於保持未指定(但有效)的狀態。這不是未定義的行爲,但它不是有用的行爲。
必須檢查每個給定的X::operator=(X&&)
的語義,檢查std
中的每種類型對於堆棧溢出答案來說「太寬泛」。他們甚至可能自相矛盾。
一般來說,當從一個對象中傳遞給對象時,您正在向消費者傳達「您不關心對象在之後的狀態」。因此,使用x = std::move(x)
是不禮貌的,因爲您(通常)做在操作完成後(正如您指定的那樣)在意x
處於什麼狀態。你在同一個操作中使用同一個對象作爲左值和右值,這並不是一種好習慣。
一個有趣的例外是默認std::swap
,這是這樣的:
template<class T>
void swap(T& lhs, T& rhs) {
T tmp = std::move(lhs);
lhs = std::move(rhs);
rhs = std::move(tmp);
}
中間線,lhs = std::move(rhs)
,做一個x = std::move(x)
如果在同一對象上調用交換兩次。
但是,請注意,我們不在乎該行在完成之後處於什麼狀態x
;我們已經在tmp
中存儲了x
的狀態,我們將在下一行中恢復它。
圖書館認爲'std :: move(x)',或一般的rvalues,因爲「別人別名」。我發現了一個有用的觀點。 –
*「使用'x = std :: move(x)''因此是不禮貌的」*然而它可能發生在通用的'swap'中,可能在一些算法中。 – dyp
@dyp'template
- 1. 要返回std :: move(x)還是不?
- 2. 在std :: move(x)上執行一些操作
- 3. rvalue refs和std :: move
- 4. std :: move和std :: copy是否一致?
- 5. req.body undefined in expressjs4.x
- 6. std :: cout << x;和std :: cout << x << std :: endl;?
- 7. std :: move VS std ::轉發
- 8. std :: unique_ptr :: release()vs std :: move()
- 9. 爲什麼JSLint推薦x ===「undefined」與typeof x ==「undefined」?
- 10. 在快遞4.x req.body是undefined
- 11. 什麼是JavaScript中的「undefined x 1」?
- 12. 在std :: thread中使用std :: move
- 13. 爲什麼std :: move undefined,雖然編譯器用-std = C++ 11調用?
- 14. move-semantics和std :: future
- 15. shared_from_this()返回std :: shared_ptr <const X>,而不是std :: shared_ptr <X>
- 16. document.getElementById(「x」)。checked返回undefined
- 17. 什麼是std :: move的類型?
- 18. std :: move的逆是否存在?
- 19. x = 20; x = ++ x + ++ x + x ++; java中x的最終值是65
- 20. 爲什麼std :: move使用std :: remove_reference?
- 21. 用std :: move()釋放內存?
- 22. std :: move結果切片嗎?
- 23. 爲什麼x ++ - + - ++ x合法但是x +++ - +++ x不是?
- 24. C++ x + = 1 x ++和x = x + 1是不是一樣?
- 25. 使用move()代替std :: move()會有什麼缺陷嗎?
- 26. CRYSTAL REPORT什麼是x:= x;?
- 27. 是什麼X ++和++ X
- 28. 什麼是var x = x || {};
- 29. 函數x不是程序或者是undefined
- 30. 處理兩個標準::對(X,Y)相同的std ::對(Y,X)
它是(用戶)實現定義的,它具有與傳統賦值運算符相同的問題。 –
它有什麼意義? – inf
@πάνταῥεῖuuum,什麼?這是一個賦值,而不是初始化...顯然'x'需要首先聲明,並且不必*不需要初始化即可聲明。所以假設OP意味着將初始化對象移動到自身上,如果這觸發了UB,那麼不是缺少初始化。移動意味着對象「處於未指定但有效的狀態」(這是標準如何制定的)。 –