2014-09-10 76 views
3

我自己研究C++ 11的特性,並識別移動語義並嘗試將它應用於至少每個處理容器或「更大」對象的函數。現在我發現了一些我想並行運行的任務,所以我會使用std :: future,但這些任務處理容器(在我的情況下返回一個容器)。 所以我有這樣的僞代碼:move-semantics和std :: future

std::future<container&&> c = std::async([]()->container&&{ /* stuff return a local container object */ }); 

,知道我問自己的壽命是如何控制的容器RVAL裁判的?如果我是正確的,並且在我調用c.get()之前完成任務,它將被存儲。存儲的值是否仍然包含可用對象?

這是否確保它的壽命?

std::future<container> c = std::async([]()->container&&{ /* same stuff --^-- */ }); 
container cc = std::move(c.get()); 
+1

做'/ * stuff * /'創建'容器'作爲本地對象嗎? – 2014-09-10 10:23:22

+1

'c.get()'已經返回一個'container &&',所以'container'中的'move' = ccd :: std :: move(c.get());'什麼也不做。 – nwp 2014-09-10 10:27:36

+1

你可能不想爲你的lambda返回一個'container &&'。 – 2014-09-10 10:34:55

回答

5

看起來好像你在做移動語義錯誤。

你應該返回值,而不是通過右值引用,並讓移動構造函數確保按值返回是有效的。否則,你可能會冒險返回一個不再存在的對象的懸掛引用。移動語義的要點是通過價值便宜的方式創建傳遞對象,右值引用僅僅是實現這一點的語言功能,但目標不應該是爲了自己的緣故使用右值引用。

換句話說,你想從lambda體的數據移動到lambda的返回值到未來的存儲值。那移動的數據。你不想傳遞一個引用,那不是移動什麼(你可以通過引用在C++ 03中使用左值引用來傳遞事物!)

你的lambda應該按值返回,並且該future應值存儲:

std::future<container> c = std::async([]()->container{ /* stuff */ }); 

而你並不需要使用std::move,獨特的期貨返回存儲的值作爲右值,所以你可以從它移動,而無需使用std::move它轉換爲一個右值自動:

container cc = c.get(); // cc will be move constructed 
+0

感謝您的即時編輯。所以我不需要執行移動的用法?如果我說得對,左值將導致副本和右值導致移動(如果可能)? '懸掛參考'這就是我在寫關於終身的時候的意思。 – JoshuaBehrens 2014-09-10 10:45:39

+1

是的,左值被複制,右值可以移動。所有'std :: move'都會將某些東西轉換爲右值,在已經是右值的東西上使用它是多餘的。 – 2014-09-10 10:50:13

+1

@JoshuaBehrens左值被複制,除非編譯器能夠刪除該副本。如果你的lambda返回一個'container'的本地實例,不要在return語句中移動它。 IOW,這將允許NRVO'[](){container c;/* stuff */return c; '',而移動不會。 – 2014-09-10 11:58:34

相關問題