我不知道當我有這樣的功能,會發生什麼C++ 11會發生什麼?當函數返回
'temp'在被銷燬之前被拷貝到一個臨時的r值(超出範圍)並且C++ 11可能被NRVO優化(所以'temp'的拷貝被直接寫入返回目的地插槽)?
我不知道當我有這樣的功能,會發生什麼C++ 11會發生什麼?當函數返回
'temp'在被銷燬之前被拷貝到一個臨時的r值(超出範圍)並且C++ 11可能被NRVO優化(所以'temp'的拷貝被直接寫入返回目的地插槽)?
什麼都應該被複制。有兩種可能性:
temp
被移動到調用者範圍內的對象;或者temp
成爲調用者範圍中對象的別名。這被稱爲「返回值優化」。在2011年之前(具體而言,沒有移動語義),第一種情況需要複製而不是移動。第二種情況允許在C++ 98和11中使用。
在'std :: unordered_map
這通常會在沒有任何特殊規則的情況下從temp
複製到函數的返回值。但是,標準中有兩條規則旨在改善這一點。第一個是,該拷貝可以被省略(12.8/31):比
在與類返回類型的函數返回語句,當表達是一種非揮發性的自動對象的名稱(其他一個功能或catch子句參數)用相同cvunqualified類型作爲函數返回類型時,複製/移動操作可以通過直接構建自動物體插入函數的返回值
這通常稱爲命名被省略返回值優化(NRVO),return value optimization (RVO)的特例。
第二個問題是,由於這種情況下滿足複製省略上述標準,它將首先被認爲是移動(12.8/32):
當的複製操作的省音的標準是滿足或將被滿足,除了源對象是函數參數,並且要被複制的對象由左值指定的情況下,首先執行用於選擇副本的構造函數的重載解析,就好像該對象由右值。
因此,編譯器將嘗試以下步驟:
注意的是,類必須有一張移動或拷貝構造函數這個工作,即使移動或複製會被省略。
NRVO意味着temp
本身是在返回值位置構造的。沒有RVO,是的,temp
被複制/從堆棧中的位置移動到被銷燬之前的返回值位置。
在沒有RVO的C++ 11中,它應該被移動,而不是被複制。 –
複製最有可能通過C++ 03 *和* C++ 11中的NRVO消除。 – juanchopanza
它可能是:a)如果移動ctor可用,則移動;或b)如果第一個不起作用,則複製。當然,(N)RVO可以同時應用兩次。 – Xeo
既然你不需要'b'的副本,第二個參數應該改成'const stringmap&b'。對於第一個,我建議將它移動到'temp',即'stringmap temp(std :: move(a));'。這不會破壞NRVO,所以返回值仍然是最優化的。 –