Pergunta

Um dos fresco novos recursos da próxima C ++ padrão, C ++ 0x, são "referências rvalue." Uma referência rvalue é semelhante a uma referência Ivalue (normal), a não ser que possa ser ligado a um valor temporário (normalmente, uma lata temporário só pode ser ligado a uma referência const):

void FunctionWithLValueRef(int& a) {...}
void FunctionWithRValueRef(int&& a) {...}

int main() {
     FunctionWithLValueRef(5); // error, 5 is a temporary
     FunctionWithRValueRef(5); // okay
}

Então, por que inventar um novo tipo, em vez de apenas remover as restrições sobre referências normais para permitir que eles sejam obrigados a temporários?

Foi útil?

Solução

Seria inútil. Você mudaria a coisa na função, ea mudança seria perdido imediatamente, porque a coisa era realmente um temporário.

A razão para o novo tipo decorre da necessidade de ser capaz de decidir o que realmente é um rvalue e quais não. Só então você pode realmente usá-los para as coisas legais que eles são usados.

string toupper(string && s) { // for nonconst rvalues
    for(char &c : s) make_uppercase(c);
    return move(s); // move s into a returned string object
}

string toupper(string const& s) { // for the rest
    // calls the rvalue reference version, by passing 
    // an rvalue copy.
    return toupper(string(s));
}

Agora, se você tem algum rvalue e passá-lo para toupper, o rvalue pode ser diretamente modificado, porque sabemos que o temporário é uma coisa descartável de qualquer maneira, para que possamos aswell apenas alterá-lo e não precisa copiar isto. Além disso, a mesma observação é usado para a coisa chamada Move-construtores e move-atribuição. O lado direito não é copiado, mas suas coisas estão apenas roubado e se mudou para *this.

Se você dissesse que rvalues ??pode ligar-se a referências lvalue não-const, então você não teria nenhuma maneira de descobrir se que referencia um lvalue (nomeado objeto) ou um rvalue (temporária) no final.


É provavelmente pouco saber mais, mas de qualquer maneira útil, você pode colocar ref-eliminatórias lvalue ou rvalue em uma função de membro. Aqui está um exemplo, o que naturalmente se estende a semântica existentes de referências rvalue para o parâmetro de objeto implícito:

struct string {
    string& operator=(string const& other) & { /* ... */ }
};

Agora, você não pode mais dizer

string() = "hello";

O que é confuso e não é realmente fazer sentido na maioria das vezes. O que o & acima faz é dizer que o operador de atribuição só pode ser invocado em lvalues. O mesmo pode ser feito para rvalues, colocando &&.

Outras dicas

Como adicionar um novo tipo de referência permite que você escreva duas sobrecargas de um método:

void CopyFrom(MyClass &&c)
{
    dataMember.swap(c);
}

void CopyFrom(const MyClass &c)
{
    dataMember.copyTheHardWay(c);
}

A versão que aceita o novo tipo de referência é permitido modificar a variável que recebe, porque essa variável não vai ser usado em qualquer outro lugar. Assim, ele pode "roubar" o conteúdo do mesmo.

Esta é toda a razão foi adicionado esse recurso; mantendo um tipo de referência não alcançar o objetivo desejado.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top