O que são rvalues, lvalues, xvalues, glvalues e prvalues em C++?
Categorias principais de valores em C++11 e posteriores
Você está certo: no C++11 a classificação ficou mais complexa por causa da move-semantics. Em vez de duas categorias (lvalue/rvalue), agora temos cinco. Vamos simplificar:
- lvalue (left value): um objeto que tem um endereço e pode estar à esquerda de uma atribuição. Exemplo: variável
x. - rvalue (right value): um valor temporário que não tem endereço persistente. Exemplo:
5oux + 5. - xvalue (expiring value): um valor que está prestes a expirar, como o resultado de
std::move(x). Ele pode ser movido, mas ainda tem um endereço. - glvalue (generalized lvalue): inclui lvalues e xvalues — tudo que tem identidade (endereço).
- prvalue (pure rvalue): inclui rvalues tradicionais que não têm identidade, como literais ou resultados de expressões.
std::move(x) é um xvalue: ele não é um lvalue (não pode ficar à esquerda de atribuição normal), mas também não é um prvalue (tem um endereço, o de x). Ele permite que o conteúdo de x seja movido para outro lugar.
As categorias se relacionam com move-semantics porque xvalues permitem que objetos sejam "roubados" (movidos) em vez de copiados, otimizando o desempenho com objetos temporários.