С++ 0x "перейти от" контейнера

В С++ 0x мы получаем повышение эффективности в отношении контейнеров с std::move:

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

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

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

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

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

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

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

Ответ 1

Возможно, я ошибаюсь, но это не то, что вы хотите просто

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

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

Ответ 2

Для полноты (и любой, кто наткнулся на этот вопрос без компилятора С++ 1x), альтернатива, которая уже существует сегодня:

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

Для типа элемента просто требуется специализация std::swap.

Ответ 3

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
}

Ответ 4

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

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

   // copy constructors here....

private:
   ExpensiveWrapper* mPtr;

};