2012-11-19 49 views
4

我有一個類,它擁有一個指向大量分配內存和大量基元類型成員的指針。我對移動構造函數感興趣,並認爲這是使用它的絕好機會。很顯然,指針應該移動過來,但是如果對基元來說是個好主意,那麼它就是idk。移動構造函數過度衝擊

下面是類的一個人爲的例子:

class Foo { 
private: 
    long m_bar = 1; 
    /* 20+ similar members */ 
}; 

爲了讓他們移動,他們將不得不被動態分配。

class Foo { 
public: 
    Foo(Foo && rhs) : m_bar(rhs.m_bar) { rhs.m_bar = nullptr; } 
    ~Foo() { delete m_bar; } 
private: 
    long *m_bar = new long{1}; 
}; 

我的問題是,在堆上分配的開銷是否會使移動語義引入的性能增加無效?

+2

「原始材料」是可移動的。 –

+0

抱歉太天真了,但你能詳細說明一下嗎? –

+0

沒有什麼需要說明的:你不需要做任何事情來移動基本類型的對象。它只是工作。 –

回答

6

如果有什麼,我相信像這樣分配每個成員的堆將最終變慢。除了最初的堆分配之外,只在構造上執行,在堆上保存指向很多小的非連續數據成員的指針並不能很好地與CPU緩存策略搭配使用。

一些類移動得非常好,因爲它們有大量的堆內存分配(例如std :: string)。在你的情況下,移動每個指針與移動較小的數據類型一樣昂貴。我可以看到這個速度更快的唯一方法是如果你將更小的數據成員放在一個堆分配的類/結構體中(可能持有一個unique_pointer),並通過單個指針的移動來移動它們。

這就是說,這很可能是一種過早優化的情況。您可能想要讓代碼運行起來,並確定爲您的類實現更復雜的移動語義確實可以幫助您的代碼的性能。

+3

+1用於過早優化。另外,這取決於OP如何使用這個類。如果它的構建比移動更頻繁,那麼可能需要花費比構建數據結構的堆更多的代價。 –

1

如果原始圖像不是比複製指針更大也不會更昂貴,那麼動態分配它只是額外的成本。

你可能想無效原件,但不需要指針。

2

移動語義只會在移動對象的速度更快而複製它時更快。在你的例子中,情況並非如此。複製long應該是將指針複製到long的速度相同。通過動態分配每個成員來添加移動語義幾乎肯定會減慢速度,而不是加快速度。

什麼可能導致更快的移動構造函數使用PIMPL成語。您將動態分配一個包含所有成員的類,主類只包含指向該類的指針。然後,你所有的移動構造函數都必須將指針複製到實現類。