C++ "переместить из" контейнера

в C++11, мы можем получить повышение эффективности с помощью std::move когда мы хотим переместить (деструктивно скопировать) значения в контейнер:

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

но я не могу найти что-нибудь в другую сторону. Я имею в виду что-то вроде этого:

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

это чаще (копия-pop) на адаптере, как stack. Может ли существовать что-то подобное:

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

чтобы избежать копирования? И это уже существует? Я не смог найти ничего подобного в n3000.

у меня такое чувство, что я упускаю что-то болезненно очевидное (например, ненужность этого), поэтому я готов к "ru dum". :3

4 ответов


Я могу быть совершенно неправ здесь, но это не то, что вы хотите просто

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

предполагая, что SomeExpensiveType имеет конструктор перемещения. (и, очевидно, верно для вашего случая)


для полноты (и любой, кто натыкается на этот вопрос без компилятора 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
}

Как правило, для дорогих типов я думаю, что вы хотели бы нажать либо класс-оболочку, либо умный указатель в контейнер. Таким образом, вы избегаете дорогостоящих копий и вместо этого делаете только дешевые копии смарт-указателя или класса-оболочки. Вы также можете использовать необработанные указатели, если хотите ха-ха.

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

   // copy constructors here....

private:
   ExpensiveWrapper* mPtr;

};