Reference 有没有办法返回对函数中创建的变量的引用?

Reference 有没有办法返回对函数中创建的变量的引用?,reference,rust,lifetime,Reference,Rust,Lifetime,我想写一个程序,将写一个文件在两个步骤。 在程序运行之前,文件可能不存在。文件名是固定的 问题是OpenOptions.new().write()可能会失败。在这种情况下,我想调用一个自定义函数trycreate()。其思想是创建文件,而不是打开文件并返回句柄。由于文件名是固定的,trycreate()没有参数,我无法设置返回值的生存期 我如何解决这个问题 use std::io::Write; use std::fs::OpenOptions; use std::path::Path; fn

我想写一个程序,将写一个文件在两个步骤。 在程序运行之前,文件可能不存在。文件名是固定的

问题是
OpenOptions.new().write()
可能会失败。在这种情况下,我想调用一个自定义函数
trycreate()
。其思想是创建文件,而不是打开文件并返回句柄。由于文件名是固定的,
trycreate()
没有参数,我无法设置返回值的生存期

我如何解决这个问题

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");
}
有没有办法从没有参数的函数返回引用

否(除了对静态值的引用,但这些在这里没有帮助)

但是,您可能需要查看。如果将
main
中的第一行更改为

let  f = OpenOptions::new().write(true).create(true).open(b"foo.txt");
如果文件尚不存在,将创建该文件,这将解决您原来的问题

有没有办法从没有参数的函数返回引用

否(除了对静态值的引用,但这些在这里没有帮助)

但是,您可能需要查看。如果将
main
中的第一行更改为

let  f = OpenOptions::new().write(true).create(true).open(b"foo.txt");
如果文件尚不存在,将创建该文件,这将解决您原来的问题。

您所问的问题 TL;DR:不,不能返回对函数所拥有的变量的引用。如果您创建了变量,或者将变量的所有权作为函数参数,则此项适用

解决 与其尝试返回引用,不如返回一个拥有的对象
String
代替
&str
Vec
代替
&T
T
代替
&T
,等等

如果通过参数获得变量的所有权,请尝试使用(可变)引用,然后返回具有相同生存期的引用

在极少数情况下,可以使用不安全代码返回所拥有的值和对该值的引用。这有许多微妙的要求,你必须坚持,以确保你不会造成未定义的行为或记忆不安全

另见:

更深层次的回答 ,但我想更深入地评论一下,并谈谈代码中的其他一些错误

让我们从返回引用的较小示例开始,并查看错误:

fn try_create<'a>() -> &'a String {
    &String::new()
}
有没有办法从没有参数的函数返回引用

从技术上说,是的,但对于你想要的,是的

引用指向现有内存块。在没有参数的函数中,唯一可以引用的是全局常量(具有生存期
&'static
)和局部变量。现在我将忽略全局

在C语言或C++语言中,你可以引用一个局部变量并返回它。但是,一旦函数返回,就不能保证所引用的内存继续保持原来的状态。它可能会像您期望的那样保持一段时间,但最终内存将被重新用于其他用途。只要代码查看内存并尝试将用户名解释为用户银行帐户中的剩余金额,就会出现问题

这是Rust的生命周期所阻止的-不允许使用引用的值超过其在当前内存位置的有效时间

另见:

你的实际问题 请参阅以下文档:

这会使用一条有用的错误消息来惊慌。当然,在程序内部惊慌失措并不是非常有用,因此建议将错误传播出去:

fn trycreate() -> io::Result<File> {
    OpenOptions::new().write(true).open("foo.txt")
}
我还将从
main
返回
结果。总之,包括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(())
}
使用std::{
fs::OpenOptions,
io::{self,Write},
};
fn main()->io::Result{
让mut f=OpenOptions::new()
.create(true)
.写(真)
.append(true)
.open(“foo.txt”)?;
f、 写入所有(b“test1\n”)?;
f、 写入所有(b“test2\n”)?;
好(())
}
你问的问题 TL;DR:不,不能返回对函数所拥有的变量的引用。如果您创建了变量,或者将变量的所有权作为函数参数,则此项适用

解决 与其尝试返回引用,不如返回一个拥有的对象
String
代替
&str
Vec
代替
&T
T
代替
&T
,等等

如果通过参数获得变量的所有权,请尝试使用(可变)引用,然后返回具有相同生存期的引用

在极少数情况下,可以使用不安全代码返回所拥有的值和对该值的引用。这有许多微妙的要求,你必须坚持,以确保你不会造成未定义的行为或记忆不安全

另见:

更深层次的回答 ,但我想更深入地评论一下,并谈谈代码中的其他一些错误

让我们从返回引用的较小示例开始,并查看错误:

fn try_create<'a>() -> &'a String {
    &String::new()
}
有没有办法从没有参数的函数返回引用

从技术上说,是的,但对于你想要的,是的

引用指向现有内存块。在没有参数的函数中,唯一可以引用的是全局常量(具有生存期
&'static
)和局部变量。现在我将忽略全局

在C语言或C++语言中,你可以引用一个局部变量并返回它。但是,一旦函数返回,就不能保证所引用的内存继续保持原来的状态。它可能会像你期望的那样保持一段时间,但最终

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(())
}
fn run() -> Box<u32> {
    let x: u32 = 42;
    return Box::new(x);
} 

fn main() {
    println!("{}", run());
}
fn run() -> u32 {
    let x: u32 = 42;
    return x;
}