2013-07-09 58 views
2

在C++ 11標準下,是否保證將下列對移入函數中?這對會被搬走嗎?

//objects available: key, value 
//corresponding type available: pairtype 
//function available: void foo(pairtype pair); copies the pair by default 

foo({std::move(key),std::move(value)}); //pair moved? 

還是我必須自己動手?

foo(std::move(pairtype(std::move(key),std::move(value))); //needed? 

回答

8

初始值設定項列表不是表達式,所以它們沒有類型,也沒有產生值。這意味着以下幾點:

{std::move(key),std::move(value)} 

本身打造一雙。初始化列表只是一個用於初始化的語法結構,在這種情況下,函數參數將由直接構造調用構造函數pairtypestd::move(key)std::move(value)作爲參數。

沒有創建臨時參數 - 唯一需要注意的是在執行列表初始化時不會考慮構造函數(例如,這對std::tuple<>的實例不起作用)。

這意味着foo調用我們剛纔討論的,即:

foo({std::move(key),std::move(value)} 

從該調用技術上是不同的:

foo(std::move(pairtype(std::move(key),std::move(value))) 

在這裏,你是有意創建一個臨時的,並將其移入函數參數(編譯器可能會按照12.8/31刪除此移動,但這是另一回事)。

請注意,此處調用std::move()是多餘的,因爲臨時值是rvalues。無論如何,函數參數將從臨時對象移動構建。因此,你可以這樣寫:

foo(pairtype(std::move(key),std::move(value))) 

通知書的,pairtype將是std::pair<>類模板的實例,這意味着你將不得不手動指定模板參數。爲了避免這種情況,你可以使用std::make_pair()

foo(std::make_pair(std::move(key),std::move(value))) 
+0

我認爲明確的構造函數只不與列表複製initalization認爲,這將是固定在C++ 14 – TemplateRex

+2

@TemplateRex:不知道關於C++ 14,但在C++ 11中,將參數傳遞給函數是複製初始化上下文(請參見8.5/15和8.5.4/1)。由於這裏我們是列表初始化,這是一個複製列表初始化(見8.5.4/1),適用的是8.5.4/3(第4個項目符號)和13.3.1.7/1。 –

+0

啊是的,我太快讀了Q.那麼這同樣適用於'emplace'就像函數(採用右值引用)?他們是否也可以不調用顯式構造函數? – TemplateRex