std::move e std::forward
Converta lvalues em rvalues com std::move e preserve a categoria de valor com std::forward
std::move e std::forward é uma aula grátis de C++ Academy no CoddyKit. Esta é a aula 3 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de C++ Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de C++ Academy inclui 4 aulas no total.
Dois primos, funções diferentes
std::move e std::forward são conversões realizadas em tempo de compilação. Parecem semelhantes, mas resolvem problemas diferentes.
std::move: sempre converte para rvalue
std::move(x) converte incondicionalmente x em uma referência rvalue. A função que recebe o valor pode então apropriar-se de seus recursos.
std::string s = "Hello";
std::string t = std::move(s); // move-constructs t from s
// s is now in a valid-but-unspecified stateQuando usar a movimentação
Use std::move em:
- Construtores de movimentação e operadores de atribuição por movimentação
- Ao retornar uma variável local quando quiser forçar uma movimentação (raramente necessário — o RVO geralmente se aplica)
- Ao passar uma variável local de que você não precisa mais para uma função consumidora
Implementação de std::move
É apenas um static_cast disfarçado:
template <typename T>
typename std::remove_reference<T>::type&& move(T&& t) noexcept {
return static_cast<typename std::remove_reference<T>::type&&>(t);
}std::forward: preserva a categoria
Em um modelo que usa uma referência de encaminhamento (T&&), std::forward<T>(x) converte x novamente para sua categoria original (lvalue ou rvalue). É usado para o encaminhamento perfeito.
template <typename T>
void wrapper(T&& arg) {
target(std::forward<T>(arg)); // forwards as lvalue or rvalue depending on T
}Por que o encaminhamento é necessário
Dentro do modelo, o parâmetro tem um nome — o que o torna um lvalue, mesmo que o chamador tenha passado um rvalue. std::forward recupera a categoria original.
Sem std::forward
Sem forward, todo argumento seria passado como lvalue dentro do wrapper, anulando qualquer semântica de movimentação pretendida pelo chamador.
template <typename T>
void wrapper(T&& arg) {
target(arg); // always lvalue — wrong
}Sempre especifique o parâmetro de modelo para forward
std::forward<T> exige o argumento de modelo explícito. Sem ele, o comportamento estaria incorreto.
Exemplo de encaminhamento perfeito
Uma função fábrica que encaminha argumentos do construtor preserva as distinções entre rvalue e lvalue para obter eficiência.
template <typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}Mova apenas uma vez
Cada objeto deve ser movido no máximo uma vez. Depois da movimentação, ele fica em um estado válido, mas não especificado — normalmente, você o reatribui ou o destrói. Usar um objeto do qual foi feita uma movimentação sem reatribuí-lo primeiro pode causar erros sutis.
Regras práticas
Modelo mental rápido:
- Você tem um tipo concreto e quer movê-lo →
std::move - Você tem um parâmetro de modelo e quer preservar a categoria →
std::forward<T>
Verificação rápida
Dentro de uma função de modelo com o parâmetro T&& arg, como encaminhar arg preservando sua categoria lvalue/rvalue?
Recapitulação
std::move faz uma conversão incondicional para rvalue — use-o em objetos concretos dos quais deseja apropriar-se dos recursos. std::forward<T> preserva a categoria de valor dentro de modelos genéricos — use-o para o encaminhamento perfeito.
Perguntas Frequentes
A aula “std::move e std::forward” é grátis?
Sim — o texto completo de “std::move e std::forward” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de C++ Academy, atualize para CoddyKit PRO. O curso de C++ Academy inclui 4 aulas no total.
O que vou aprender em “std::move e std::forward”?
Converta lvalues em rvalues com std::move e preserve a categoria de valor com std::forward Você pratica C++ Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar C++ Academy?
Nenhuma experiência prévia é necessária. C++ Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 3 de 4.
Quanto tempo leva a aula “std::move e std::forward”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de C++ Academy?
Sim. Cada aula de C++ Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Lvalue versus rvalue: a distinção
- Referências rvalue e a sintaxe &&
- std::move e std::forward
- Construtores de movimento e atribuição por movimento