subrutinas parametros funciones ejemplos con c++ c++11 rvalue-reference lvalue rvalue

parametros - funciones en c++ ejemplos



Rvalue Reference se trata como un Lvalue? (4)

Publiqué esta respuesta: https://stackoverflow.com/a/28459180/2642059 que contiene el siguiente código:

void foo(string&& bar){ string* temp = &bar; cout << *temp << " @:" << temp << endl; }

¿Es bar un valor r o un valor l?

Pregunto porque obviamente no puedo tomar la dirección de un valor r, pero sí puedo tomar la dirección de una referencia rvalue como se hace aquí.

Si puede realizar cualquier operación en una referencia de valor que puede hacer en una referencia de valor, ¿cuál es el punto de diferenciar entre los dos con "&&" en lugar de solo "&"?


¿Es bar un valor r o un valor l?

La pregunta se responde sola. Cualquier cosa que tenga un nombre es un lvalue (1) . Entonces la bar es un valor. Su tipo es "rvalue reference to string ", pero es un lvalue de ese tipo.

Si desea tratarlo como un valor r, debe aplicarle std::move() .

Si puede realizar cualquier operación en una referencia de valor que puede hacer en una referencia de valor, ¿cuál es el punto de diferenciar entre los dos con "&&" en lugar de solo "&"?

Esto depende de su definición de "realizar una operación". Una referencia de valor y una referencia de valor (con nombre) son prácticamente idénticas en cómo puede usarlas en expresiones, pero difieren mucho en lo que puede vincularlas. Los valores pueden unirse a las referencias de valor, los valores pueden unirse a las referencias de valor (y cualquier cosa puede unirse a una referencia de valor a const ). Es decir, no puede vincular un rvalue a una referencia de lvalue, o viceversa.

Hablemos de un parámetro de función del tipo de referencia rvalue (como su bar ). El punto importante no es qué bar es, sino qué sabe sobre el valor al que se refiere la bar . Dado que la bar es una referencia de valor, usted sabe con certeza que cualquier cosa vinculada a él era un valor. Lo que significa que seguramente se destruirá cuando termine la expresión completa, y puede tratarlo de manera segura como un valor (robando sus recursos, etc.).

Si no eres el que hace esto directamente a la bar , pero solo quieres pasar la bar , tienes dos opciones: o has terminado con la bar , y luego debes decirle al siguiente que lo recibe que está vinculado a un rvalue — do std::move(bar) . O tendrá que hacer algunas cosas más con la bar , por lo que no querrá que nadie en el medio le robe sus recursos, así que trátelo como una bar .

Para resumirlo: la diferencia no está en lo que puede hacer con la referencia una vez que la tenga. La diferencia es lo que puede unirse a la referencia.

(1) Una buena regla general, con excepciones menores: los enumeradores tienen nombres, pero son valores. Las clases, los espacios de nombres y las plantillas de clase tienen nombres, pero no son valores.


¿Es bar un valor r o un valor l ?

Es un lvalue , como lo es cualquier expresión que nombra una variable.

Si puede realizar cualquier operación en una referencia de valor que puede hacer en una referencia de valor, ¿cuál es el punto de diferenciar entre los dos con "&&" en lugar de solo "&"?

Solo puede inicializar una referencia rvalue con una expresión rvalue . Por lo tanto, puede pasar una cadena temporal a su función, pero no puede pasar una variable de cadena sin moverse explícitamente de ella. Esto significa que su función puede asumir que el argumento ya no es deseado y puede moverse de él.

std::string variable; foo(variable); // ERROR, can''t pass an lvalue foo(std::move(variable)); // OK, can explicitly move foo("Hello"); // OK, can move from a temporary


Aquí, en este caso, las referencias denominadas rvalue son valores , mientras que si el tipo de entrada es constante, las referencias rvalue serán rvalue , aquí hay un ejemplo simple:

#include <string> #include <iostream> void foo(const std::string&& bar) { std::string* temp = &bar; // compile error, can''t get address std::cout << *temp << " @:" << temp << std::endl; } int main() { foo("test"); return 0; }

Espero que esto sea útil.


La bar expresión es un valor l. Pero no es una "referencia de valor de cadena". La bar expresión es una referencia de valor. Puede verificarlo agregando la siguiente línea en foo ():

cout << is_lvalue_reference<decltype((bar))>::value << endl; // prints "1"

Pero estoy de acuerdo con el resto de la explicación de Angew.

Una referencia de valor, después de que se ha vinculado a un valor, es una referencia de valor. En realidad no es solo para parámetros de función:

string&& a = "some string"; string&& b = a; // ERROR: it does not compile because a is not an rvalue

Si puede realizar cualquier operación en una referencia de valor que puede hacer en una referencia de valor, ¿cuál es el punto de diferenciar entre los dos con "&&" en lugar de solo "&"?

Una referencia de rvalue nos permite hacer algunas "operaciones de lvalue" antes de que expire el rvalue.