C ++ "MOVE DO" RECIMENTO
-
22-09-2019 - |
Pergunta
Em C ++ 11, podemos obter um aumento de eficiência usando std::move
Quando queremos mover (copiar destrutivamente) valores para um contêiner:
SomeExpensiveType x = /* ... */;
vec.push_back(std::move(x));
Mas não consigo encontrar nada indo para o outro lado. O que quero dizer é algo assim:
SomeExpensiveType x = vec.back(); // copy!
vec.pop_back(); // argh
Isso é mais frequente (o pop-pop) no adaptador stack
. Poderia algo assim existir:
SomeExpensiveType x = vec.move_back(); // move and pop
Para evitar uma cópia? E isso já existe? Não consegui encontrar nada assim no N3000.
Tenho a sensação de que estou perdendo algo dolorosamente óbvio (como a desnecessária), então estou preparado para "ru dum". : 3
Solução
Posso estar errado aqui, mas não é o que você quer apenas
SomeExpensiveType x = std::move( vec.back() ); vec.pop_back();
Supondo que algum expenseType tenha um construtor de movimentos. (e obviamente verdadeiro para o seu caso)
Outras dicas
Para completude (e qualquer pessoa tropeçando nessa pergunta sem um compilador C ++ 1x), uma alternativa que já existe hoje:
SomeExpensiveType x;
std::swap(x, vec.back());
vec.pop_back();
Apenas requer uma especialização de std::swap
existir para o tipo de elemento.
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
}
Geralmente, para tipos caros, acho que você gostaria de empurrar uma classe de invólucro ou um ponteiro inteligente para o contêiner. Dessa forma, você está evitando cópias caras e apenas fazendo cópias baratas do ponteiro inteligente ou da classe Wrapper. Você também pode usar ponteiros crus também se quiser haha.
class ExpensiveWrapper
{
public:
ExpensiveWrapper(ExpensiveClass* in) { mPtr = in; }
// copy constructors here....
private:
ExpensiveWrapper* mPtr;
};