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;
};