No entiendo el error cannot move out of borrowed content
. Lo he recibido muchas veces y siempre lo he resuelto, pero nunca he entendido por qué.
Por ejemplo:
for line in self.xslg_file.iter() {
self.buffer.clear();
for current_char in line.into_bytes().iter() {
self.buffer.push(*current_char as char);
}
println!("{}", line);
}
produce el error:
error[E0507]: cannot move out of borrowed content
--> src/main.rs:31:33
|
31 | for current_char in line.into_bytes().iter() {
| ^^^^ cannot move out of borrowed content
En versiones más recientes de Rust, el error es
error[E0507]: cannot move out of `*line` which is behind a shared reference
--> src/main.rs:31:33
|
31 | for current_char in line.into_bytes().iter() {
| ^^^^ move occurs because `*line` has type `std::string::String`, which does not implement the `Copy` trait
Lo resolví clonando line
:
for current_char in line.clone().into_bytes().iter() {
No entiendo el error incluso después de leer otras publicaciones como:
- No se puede tomar prestado el archivo de & mut self (mensaje de error: no se puede salir del contenido prestado)
- Cambiar un nodo en un árbol en Rust
¿Cuál es el origen de este tipo de error?
.bytes()
método.).as_bytes()
as_bytes()
sin clonación. Pero todavía no entiendo por qué?String
obtiene elbytes
método destr
.Respuestas:
Veamos la firma de
into_bytes
:Esto toma
self
, no una referencia a uno mismo (&self
). Eso significa queself
se consumirá y no estará disponible después de la llamada. En su lugar, obtienes unVec<u8>
. El prefijointo_
es una forma común de denotar métodos como este.No sé exactamente qué
iter()
devuelve su método, pero supongo que es un iterador terminado&String
, es decir, devuelve referencias a unString
pero no le da la propiedad de ellos. Eso significa que no puede llamar a un método que consume el valor .Como has encontrado, una solución es usar
clone
. Esto crea un objeto duplicado que le pertenece y que puede llamarinto_bytes
. Como mencionan otros comentaristas, también puede usaras_bytes
las tomas&self
, por lo que funcionará con un valor prestado. Cuál debe usar depende de su objetivo final para lo que hace con el puntero.En la imagen más grande, todo esto tiene que ver con la noción de propiedad . Ciertas operaciones dependen de poseer el artículo, y otras operaciones pueden salirse con el préstamo del objeto (quizás mutablemente). Una referencia (
&foo
) no otorga propiedad, es solo un préstamo.La transferencia de propiedad es un concepto útil en general: cuando haya terminado con algo, alguien más puede tenerlo. En Rust, es una forma de ser más eficiente. Puedo evitar asignar una copia, darle una copia y luego tirar mi copia. La propiedad es también el estado más permisivo; si poseo un objeto, puedo hacer con él lo que desee.
Aquí está el código que creé para probar:
fuente