关于c ++ 11:C ++“从容器中移出”

C++ “move from” container

在C++ 11中,当我们想要移动(破坏性拷贝)值到容器时,可以使用EDCOX1×0来获得效率提升:

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

但我找不到任何相反的方向。我的意思是这样的:

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

这在适配器(如stack上)上更为频繁(copy pop)。是否可能存在这样的情况:

1
SomeExpensiveType x = vec.move_back(); // move and pop

为了避免复制?这已经存在了吗?我在3000号公路上找不到类似的东西。

我有一种感觉,我错过了一些显而易见的痛苦的东西(比如它的不必要性),所以我准备好了"ru dum"。:3


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

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

假设某个昂贵类型具有移动构造函数。(你的情况显然是这样)


1
2
3
4
5
6
7
8
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++ 1x编译器的情况下绊倒这个问题),一个已经存在的替代方案:

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

它只要求元素类型存在std::swap的专门化。


通常对于昂贵的类型,我认为您应该将包装类或智能指针推送到容器中。这样就避免了昂贵的副本,而只做智能指针或包装类的廉价副本。如果你想要哈哈,你也可以使用原始指针。

1
2
3
4
5
6
7
8
9
10
11
class ExpensiveWrapper
{
public:
   ExpensiveWrapper(ExpensiveClass* in) { mPtr = in; }

   // copy constructors here....

private:
   ExpensiveWrapper* mPtr;

};