C++ C++&引用;从;容器

C++ C++&引用;从;容器,c++,c++11,containers,rvalue-reference,C++,C++11,Containers,Rvalue Reference,在C++11中,当我们想要将值移动(破坏性复制)到容器中时,可以使用std::move来提高效率: SomeExpensiveType x = /* ... */; vec.push_back(std::move(x)); 但我找不到任何相反的方向。我的意思是这样的: SomeExpensiveType x = vec.back(); // copy! vec.pop_back(); // argh 在适配器的堆栈上,这种情况更为频繁(复制弹出)。可能存在这样的情况: SomeExpensi

在C++11中,当我们想要将值移动(破坏性复制)到容器中时,可以使用
std::move
来提高效率:

SomeExpensiveType x = /* ... */;
vec.push_back(std::move(x));
但我找不到任何相反的方向。我的意思是这样的:

SomeExpensiveType x = vec.back(); // copy!
vec.pop_back(); // argh
在适配器的
堆栈
上,这种情况更为频繁(复制弹出)。可能存在这样的情况:

SomeExpensiveType x = vec.move_back(); // move and pop
为了避免复制?这是否已经存在?我在n3000中找不到类似的东西


我有一种感觉,我错过了一些非常明显的东西(比如不必要的东西),所以我准备好了“ru dum”:3

我可能完全错了,但这不是你想要的

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

假设某个ExpensiveType具有移动构造函数。(对于您的情况显然是这样)

一般来说,对于昂贵的类型,我认为您应该将包装类或智能指针推入容器中。这样,您就避免了昂贵的拷贝,而只做智能指针或包装器类的廉价拷贝。你也可以使用原始指针,如果你想哈哈

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

   // copy constructors here....

private:
   ExpensiveWrapper* mPtr;

};
为了完整性(以及在没有C++1x编译器的情况下在这个问题上遇到障碍的人),今天已经存在一个替代方案:

SomeExpensiveType x;
std::swap(x, vec.back()); 
vec.pop_back();
它只需要专门化
std::swap
就可以为元素类型存在。

模板
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
}
自动弹出(C&C)->typename std::decay::type { 自动值(std::move(c.back()); c、 向后弹出(); 返回值;//还隐式使用移动语义 //RVO仍然适用于将两个移动减少为一个 }

我想到了这一点,但我对从容器中取出这样的东西很谨慎。现在我想得更多了,这似乎是完全合法的…:|@可怕:
back
返回一个引用,使用
std::move
会将其转换为右值引用。@GMan:不用担心,
move
是类提供的服务,而不是容器。容器中的对象仍保证保持有效。@Jerry:否,“移动自”对象仍有效。它存在,通常只是重置为一个非常简单的状态。它的生存期尚未到期,其析构函数尚未调用,但它将被调用。就语言而言,对象是完全有效的concerned@Jerry@jalf@Daniel:应该注意的是,标准所说的已经改变了。从FCD中,表34和36(从33移动,不相关)说:“注意:rv仍然是一个有效对象。其状态为未指定结束注释]”因此它是明确的:移动的对象需要能够安全地销毁,但没有指定其他内容。很高兴他们澄清了这一点。
move
语义的一个要点就是摆脱这种方法。容器将只移动其内容,而不是复制内容。移动方法对超出范围的变量有什么影响?例如,如果我创建了一个对象,将其添加到成员容器中,那么该对象将超出范围。。。由于没有复制,成员容器中的对象是否仍然定义?是的,它已移动到容器中。如果你不确定它们是如何工作的,你会想要谷歌右值参考。谢谢。。。我将不得不进一步深入研究这个lol。从表面上看,这似乎会导致问题。除了不要显式地使用std::swap(因为它不能针对许多类型进行专门化);对非限定交换调用使用using声明。@Roger Pate-或使用
boost::swap
来获得相同的结果。我宁愿只键入一行,也不愿担心谁会抱怨boost,因为有人不可避免地会这样做。:)@sellibitze…除非您意识到它已经是2010年了,而且标准还不完整,这意味着C++0x中“0”的原始含义已经过时。我仍然会像其他人一样称它为C++0x,但你可以这样说。有时如果我感觉不太乐观,我会使用C++2x。我发现std::decay比std::remove_引用更合适。例如,它将一个“const MyClass&”转换为一个“MyClass”(删除const)。我不是100%确定,但在
->
之后可能缺少一个
类型名。为什么看起来这应该简单得多?在某些上下文中,typename是不必要的(例如,在基类列表中)。因为只有一个类型可以跟随箭头,所以typename是相当多余的。我只是不确定这个上下文是否需要typename。@sellibitze:我对草案和当前gcc的解释agree:这里需要。