2010-12-10 82 views
0

好吧,我一直在閱讀有關rvalues,他們看起來像一個好主意,但有些事情一直在困擾着我。特別是移動的聲明允許我們竊取資源並避免複製。rvalues C++ 0x and moving to stack

我知道移動的工作原理並避免複製堆棧上發生的所有事情,但最終在堆棧上完成的大部分工作產生了一些我們希望複製到堆中的值,這是我不認爲的地方移動作品。

假設INT具有移動賦值運算符,給出下面的代碼:

struct Foo 
{ 
int x; 
}; 

void doIt() 
{ 
Foo* f = new Foo(); 
f->x = (2 + 4); 
} 

因此,在此實例中,右值從(2 + 4)得到的推測可以被移動到F-> X代替的複製。好的,太好了。但f和因此f-> x在上,並且右值在堆棧上。似乎不可能避免複製。你不能簡單地將f-> x指向右值的內存。一旦它結束,這個右值就會被吹走。副本似乎是必要的。

所以我是正確的,將複製副本? 還是我錯了? 還是我完全誤解了右值概念?

+1

看來你是誤解了一些東西。移動不是魔術,沒有比分配/複製更快的獲取int值的方法。 – UncleBens 2010-12-10 15:56:09

+0

@UncleBens嗯,我只是想確認一下。我不斷閱讀右值使事情更快,避免複製。但正如在我的例子中,我試圖確認複製確實是必需的,並且右值僅在某些特定情況下有所幫助。 – anio 2010-12-10 16:01:58

+0

標量類型的移動對象相當於複製它們。移動對於更復雜的類型變得有趣。如果您將這些事情發生在班級設計師身上,會發生什麼。您可以通過定義您自己的移動構造函數來控制此行爲。 – sellibitze 2010-12-10 20:48:43

回答

5

在這種情況下,它可能會做一個副本,但由於該對象只包含一個int,這不是什麼大問題。

您關心的時間通常是當對象包含指向堆中分配的某些數據的指針(不管對象本身分配的位置)。在這種情況下,避免分配這些數據的新副本是非常值得的(因爲即使對象本身在堆棧上,它也在堆上,無論對象本身位於何處,都可以移動它)。

+0

好點。移動可用於從一個堆位置竊取資源到另一個堆位置。所以我們可以進行堆棧到堆棧的移動。堆到堆的移動。但是沒有堆棧到堆的移動。這是我的預期。 – anio 2010-12-10 15:04:37

+1

當然,您可以將堆棧中的對象堆疊起來,反之亦然。啓用移動的類型通常不關心其移動的位置。存儲的概念與移動語義是正交的。 – sellibitze 2010-12-10 20:56:12

1

嗯。局部變量在堆棧上。你的右值將被優化到6並且最終的二進制文件最有可能在其中有一個mov [dest], 6

3

我的理解是,移動不是複製相反:運動是可取的,因爲在大多數情況下,將實施淺拷貝(而不是深拷貝)。

如果一個對象持有指向某個資源的指針,那麼淺拷貝就是複製指針,而深度拷貝是複製指針指向的數據。總是有複製涉及:問題是「我們必須走多深」。

你舉的例子只涉及一個int:有一個int的副本沒有這樣的事情,所以在這裏無關緊要。所以確實,你相信只有在涉及動態分配的資源時,移動纔有意義。

+0

移動當然不會*限於淺拷貝。這個構造函數的作用取決於你的類設計者。 – sellibitze 2010-12-11 15:38:32