2010-01-26 56 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