2010-01-26 59 views
17

「自招」在C++ 11中,我們可以通過使用std::move得到提升效率時,我們要移動(複製破壞性)值到一個容器:C++容器

SomeExpensiveType x = /* ... */; 
vec.push_back(std::move(x)); 

但我不能發現另一種方式。我的意思是這樣的:在適配器的像stack

SomeExpensiveType x = vec.back(); // copy! 
vec.pop_back(); // argh 

這是更頻繁(複印件流行)。可以這樣的事情存在:

要避免複製?這是否已經存在?我在n3000中找不到那樣的東西。

我有一種感覺,我失去了一些痛苦明顯的東西(比如它的不必要的東西),所以我準備爲「ru dum」做準備。 :3

+0

移動方法對超出範圍的變量有什麼影響?例如,如果我創建了一個對象,將其添加到成員容器中,那麼該對象將超出作用域...由於沒有創建副本,成員容器中的對象是否仍然定義? – Polaris878 2010-01-26 22:19:03

+0

是的,它被移入容器中。如果你不確定它們是如何工作的,你會想要谷歌右值引用。 – GManNickG 2010-01-26 22:21:41

+0

甜蜜的感謝...我將不得不深入這個更多的哈哈。在表面看來,這似乎會導致問題。 – Polaris878 2010-01-26 22:33:19

回答

15

我可能會在這裏總不會錯,但是是不是你想要的只是

SomeExpensiveType x = std::move(vec.back()); vec.pop_back(); 

假設SomeExpensiveType有一個移動構造函數。 (對你的情況顯然是這樣)

+0

我想到了這一點,但我很擔心從容器中移動東西。現在我想更多了,它似乎完全合法......:| – GManNickG 2010-01-26 22:08:07

+0

嗯。我不確定這是否正確。毫無疑問,vec.back()必須具有移動語義,即返回一個&& – ScaryAardvark 2010-01-26 22:20:26

+0

請注意,我已經考慮了一些,你可能是對的。 – ScaryAardvark 2010-01-26 22:21:17

-1

通常對於昂貴的類型,我認爲你想要將包裝類或智能指針推入容器中。這樣你就可以避免昂貴的副本,而只需要做便宜的智能指針或包裝類。如果你想哈哈,你也可以使用原始指針。

class ExpensiveWrapper 
{ 
public: 
    ExpensiveWrapper(ExpensiveClass* in) { mPtr = in; } 

    // copy constructors here.... 

private: 
    ExpensiveWrapper* mPtr; 

}; 
+3

「移動」語義學的一點是擺脫這種方法。容器只會「移動」其內容而不是複製它們。 – GManNickG 2010-01-26 22:12:18

4

爲了完整(和任何人在這個問題上磕磕絆絆沒有C++編譯器1X),已經存在今天的備選:

SomeExpensiveType x; 
std::swap(x, vec.back()); 
vec.pop_back(); 

它只是需要的std::swap一個專業化的存在元素類型。

+3

除了不明確使用std :: swap(因爲它不能專門適用於很多類型);使用具有非限定交換呼叫的使用聲明。 – 2010-10-01 10:56:56

+1

@Roger Pate - 或使用'boost :: swap'來獲得相同的結果。 – 2010-10-01 13:00:52

+0

我寧願輸入一行,也不願擔心誰會抱怨Boost,因爲某些人不可避免地會這樣做。 :) – 2010-10-01 13:07:43

4
template<class C> 
auto pop_back(C& c) -> typename std::decay<decltype(c.back())>::type 
{ 
    auto value (std::move(c.back())); 
    c.pop_back(); 
    return value; // also uses move semantics, implicitly 
    // RVO still applies to reduce the two moves to one 
} 
+0

我發現std :: decay比std :: remove_reference更合適。例如,它將「const MyClass&」變成「MyClass」(移除const)。 – sellibitze 2010-10-01 19:42:57

+0

@sellibitze:你說得對,那是比較合適的;謝謝! – 2010-10-01 20:28:21

+0

我不是100%肯定的,但是''typename''可能在' - >' – sellibitze 2010-10-03 02:19:09