2009-05-09 6 views
20

Una de las nuevas características geniales del próximo estándar C++, C++ 0x, son las "referencias rvalue". Una referencia rvalue es similar a una referencia de valor-I (normal), excepto que se puede enlazar a un valor temporal (normalmente, un temporal solo se pueden unir a una referencia const):¿Por qué C++ 0x rvalue reference no es el valor predeterminado?

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

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

Así que, ¿por qué inventar un tipo completamente nuevo, en lugar de simplemente eliminar las restricciones de las referencias normales para permitir que se vinculen a los temporales?

+3

Me pregunto por qué esto obtuvo 3 votos pero 7 favoritos. No creo haber favorecido alguna vez una pregunta sin votarla (a menos que no obtuviera votos o que estuviera bloqueada). – Zifre

+3

Me pregunto por qué alguien piensa de alguna manera y luego espera que todos los demás hagan exactamente lo mismo que él. – user534498

+1

Me pregunto por qué "ser amable y dar un voto positivo" es una expectativa irracional. –

Respuesta

43

No tendría sentido. Cambiarías la cosa en la función, y el cambio se perdería inmediatamente porque la cosa era en realidad temporal.

El motivo del nuevo tipo surge de la necesidad de poder decidir qué es realmente un valor r y qué no. Solo entonces puedes usarlos para las cosas geniales que se usan.

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

Ahora, si tiene algún valor de lado derecho y pasarlo a toupper, el valor de lado derecho se puede directamente ser modificado, porque sabemos que el temporal es una cosa de usar y tirar de todos modos, por lo que puede aswell simplemente cambiarlo y don' Necesito copiarlo. Además, la misma observación se usa para lo que se llama movimiento-constructores y movimiento-asignación. El lado derecho no se copia, pero sus cosas se acaban de robar y se mueven al *this.

Si dijera que los rvalues ​​pueden vincularse a las referencias de lvalue no const, entonces no tendría forma de averiguar si eso hace referencia a un lvalue (objeto con nombre) o un valor de r (temporal) al final.


Es probablemente más pocos conocimientos, pero útil de todos modos, se puede poner REF-calificadores lvalue o rvalue en una función miembro. Este es un ejemplo, que, naturalmente, se extiende la semántica de referencias existentes rvalue al parámetro objeto implícito:

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

Ahora, no se puede decir más

string() = "hello"; 

Cuál es confuso y no es realmente hacer sentir la mayor parte del tiempo. Lo que hace el & anterior es decir que el operador de asignación solo puede invocarse en lvalues. Lo mismo se puede hacer para los valores r, poniendo &&.

+1

+1 ¡Guau, gracias por la última parte sobre la llamada al miembro lvalues ​​/ rvalues ​​only!Leí mucho sobre C++ 0x pero no vi nada al respecto (creo que está en el último borrador, pero no lo leí todo). ¿Me puede indicar alguna documentación sobre esta característica? – Klaim

+0

Aquí hay una buena visión general: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1821.htm. En el documento de trabajo, véanse 8.3.5, 9.3.1 y 13.3.1. –

+0

Gracias por esta respuesta, esto lo hace mucho más claro. Simplemente no entendía muy bien las referencias de valores. Esto tiene mucho más sentido de lo que estaba pensando. – Zifre

12

Debido a la adición de un nuevo tipo de referencia que permite escribir dos sobrecargas de un método:

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

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

La versión que acepta el nuevo tipo de referencia se le permite modificar la variable que recibe, ya que ISN variables No se usará en ningún otro lado. Entonces puede "robar" su contenido.

Este es el motivo por el que se ha agregado esta característica; retener un tipo de referencia no alcanzaría el objetivo deseado.

Cuestiones relacionadas