Ответ 1
Возможно, я ошибаюсь, но это не то, что вы хотите просто
SomeExpensiveType x = std::move( vec.back() ); vec.pop_back();
Предполагая, что SomeExpensiveType имеет конструктор перемещения. (и, очевидно, верно для вашего случая)
В С++ 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
Возможно, я ошибаюсь, но это не то, что вы хотите просто
SomeExpensiveType x = std::move( vec.back() ); vec.pop_back();
Предполагая, что SomeExpensiveType имеет конструктор перемещения. (и, очевидно, верно для вашего случая)
Для полноты (и любой, кто наткнулся на этот вопрос без компилятора С++ 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;
};