variable valor una referencia que programacion por paso pasar pasaje parametros otra metodos metodo funciones definicion clase argumentos reference rust lifetime

reference - referencia - pasar el valor de una variable de una clase a otra c#



¿Hay alguna forma de devolver una referencia a una variable creada en una función? (2)

¿Hay alguna manera de devolver una referencia de una función sin argumentos?

No (excepto las referencias a valores estáticos, pero aquí no son útiles).

Sin embargo, es posible que desee ver OpenOptions::create . Si cambia su primera línea en main a

let f = OpenOptions::new().write(true).create(true).open(b"foo.txt");

el archivo se creará si aún no existe, lo que debería resolver su problema original.

Quiero escribir un programa que escriba un archivo en 2 pasos. Es probable que el archivo no exista antes de ejecutar el programa. El nombre del archivo es fijo.

El problema es que OpenOptions.new().write() puede fallar. En ese caso, quiero llamar a una función personalizada trycreate() . La idea es crear el archivo en lugar de abrirlo y devolver un identificador. Como el nombre de archivo es fijo, trycreate() no tiene argumentos y no puedo establecer una vida útil del valor devuelto.

¿Como puedo resolver este problema?

use std::io::Write; use std::fs::OpenOptions; use std::path::Path; fn trycreate() -> &OpenOptions { let f = OpenOptions::new().write(true).open("foo.txt"); let mut f = match f { Ok(file) => file, Err(_) => panic!("ERR"), }; f } fn main() { { let f = OpenOptions::new().write(true).open(b"foo.txt"); let mut f = match f { Ok(file) => file, Err(_) => trycreate("foo.txt"), }; let buf = b"test1/n"; let _ret = f.write(buf).unwrap(); } println!("50%"); { let f = OpenOptions::new().append(true).open("foo.txt"); let mut f = match f { Ok(file) => file, Err(_) => panic!("append"), }; let buf = b"test2/n"; let _ret = f.write(buf).unwrap(); } println!("Ok"); }


fjh es absolutamente correcto , pero quiero comentar un poco más profundamente y tocar algunos de los otros errores con su código.

Comencemos con un ejemplo más pequeño de devolver una referencia y observe los errores:

fn try_create<''a>() -> &''a String { &String::new() }

Rust 2015

error[E0597]: borrowed value does not live long enough --> src/lib.rs:2:6 | 2 | &String::new() | ^^^^^^^^^^^^^ temporary value does not live long enough 3 | } | - temporary value only lives until here | note: borrowed value must be valid for the lifetime ''a as defined on the function body at 1:15... --> src/lib.rs:1:15 | 1 | fn try_create<''a>() -> &''a String { | ^^

Rust 2018

error[E0515]: cannot return reference to temporary value --> src/lib.rs:2:5 | 2 | &String::new() | ^------------- | || | |temporary value created here | returns a reference to data owned by the current function

¿Hay alguna manera de devolver una referencia de una función sin argumentos?

Técnicamente "sí", pero para lo que quieres, "no".

Una referencia apunta a una pieza de memoria existente. En una función sin argumentos, las únicas cosas a las que se podría hacer referencia son las constantes globales (que tienen la vida útil &''static ) y las variables locales. Ignoraré los globales por ahora.

En un lenguaje como C o C ++, podría tomar una referencia a una variable local y devolverla. Sin embargo, tan pronto como la función regrese, no hay garantía de que la memoria a la que hace referencia continúe siendo lo que pensaba que era. Podría permanecer lo que espera por un tiempo, pero eventualmente la memoria se reutilizará para otra cosa. Tan pronto como su código mire la memoria e intente interpretar un nombre de usuario como la cantidad de dinero que queda en la cuenta bancaria del usuario, ¡surgirán problemas!

Esto es lo que previene la vida útil de Rust: no puede usar una referencia más allá de cuánto tiempo el valor al que se hace referencia es válido en su ubicación de memoria actual.

En lugar de intentar devolver una referencia, devuelva un objeto propio. String lugar de &str , Vec<T> lugar de &[T] , T lugar de &T , etc.

Ver también:

  • ¿Es posible devolver un tipo prestado o propio en Rust?
  • ¿Por qué puedo devolver una referencia a un literal local pero no a una variable?

Tu problema real

Mire la documentación de OpenOptions::open :

fn open<P: AsRef<Path>>(&self, path: P) -> Result<File>

Devuelve un Result<File> , por lo que no sé cómo esperaría devolver un OpenOptions o una referencia a uno. Su función funcionaría si la reescribiera como:

fn trycreate() -> File { OpenOptions::new() .write(true) .open("foo.txt") .expect("Couldn''t open") }

Esto utiliza Result::expect entrar en pánico con un mensaje de error útil. Por supuesto, entrar en pánico en las entrañas de su programa no es súper útil, por lo que se recomienda propagar sus errores:

fn trycreate() -> io::Result<File> { OpenOptions::new().write(true).open("foo.txt") }

Option y Result tienen muchos buenos métodos para lidiar con la lógica de error encadenado. Aquí, puedes usar or_else :

let f = OpenOptions::new().write(true).open("foo.txt"); let mut f = f.or_else(|_| trycreate()).expect("failed at creating");

También devolvería el Result de main . Todos juntos, incluidas las sugerencias de fjh:

use std::{ fs::OpenOptions, io::{self, Write}, }; fn main() -> io::Result<()> { let mut f = OpenOptions::new() .create(true) .write(true) .append(true) .open("foo.txt")?; f.write_all(b"test1/n")?; f.write_all(b"test2/n")?; Ok(()) }