¿Por qué es legal pedir prestado un temporal?

Resuelto Sven Marnach asked hace 6 años • 3 respuestas

Viniendo de C++, me sorprende bastante que este código sea válido en Rust:

let x = &mut String::new();
x.push_str("Hello!");

En C++, no se puede tomar la dirección de un temporal, y un temporal no sobrevivirá a la expresión en la que aparece.

¿Cuánto tiempo vive el temporal en Rust? Y como xes sólo un préstamo, ¿quién es el dueño de la cadena?

Sven Marnach avatar Dec 06 '17 03:12 Sven Marnach
Aceptado

¿Por qué es legal pedir prestado un temporal?

Es legal por la misma razón que es ilegal en C++: porque alguien dijo que así debería ser .

¿Cuánto tiempo vive el temporal en Rust? Y como xes sólo un préstamo, ¿quién es el dueño de la cadena?

La referencia dice :

el alcance temporal de una expresión es el alcance más pequeño que contiene la expresión y es para uno de los siguientes:

  • Todo el cuerpo funcional.
  • Una declaración.
  • El cuerpo de a ifo whileexpresión loop.
  • El elsebloque de una ifexpresión.
  • La expresión de condición de una expresión ifo while, o un match guardia.
  • La expresión para un brazo de cerilla.
  • El segundo operando de una expresión booleana diferida .

Básicamente, puedes tratar tu código como:

let mut a_variable_you_cant_see = String::new();
let x = &mut a_variable_you_cant_see;
x.push_str("Hello!");

Ver también:

  • ¿Por qué puedo devolver una referencia a un literal local pero no a una variable?
  • ¿Cuál es el alcance de los valores sin nombre?
  • ¿Están bien los punteros sin formato a los temporales en Rust?
Shepmaster avatar Dec 05 '2017 20:12 Shepmaster

De la referencia de Rust :

Vidas temporales

Cuando se utiliza una expresión de valor en la mayoría de los contextos de expresión de lugar, se crea una ubicación de memoria temporal sin nombre inicializada con ese valor y la expresión se evalúa en esa ubicación.

Esto se aplica porque String::new()es una expresión de valor y al estar justo debajo &mutestá en un contexto de expresión de lugar. Ahora el operador de referencia solo tiene que pasar por esta ubicación de memoria temporal, por lo que se convierte en el valor de todo el lado derecho (incluido &mut).

Sin embargo, cuando se crea una expresión de valor temporal que se asigna a una declaración let, el temporal se crea con la vida útil del bloque adjunto.

Dado que está asignado a la variable, tiene una vida útil hasta el final del bloque adjunto.

Esto también responde a esta pregunta sobre la diferencia entre

let a = &String::from("abcdefg"); // ok!

y

let a = String::from("abcdefg").as_str(); // compile error

En la segunda variante, el temporal se pasa a as_str(), por lo que su duración finaliza al final de la declaración.

starblue avatar Jun 12 '2018 13:06 starblue