C ++ "переместить из" контейнера - PullRequest
17 голосов
/ 27 января 2010

В C ++ 11 мы можем повысить эффективность, используя 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

Ответы [ 4 ]

17 голосов
/ 27 января 2010

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

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

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

4 голосов
/ 01 октября 2010
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 голосов
/ 08 апреля 2010

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

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

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

0 голосов
/ 27 января 2010

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

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

   // copy constructors here....

private:
   ExpensiveWrapper* mPtr;

};
...