Nex*_*Nex 31 reference lifetime rust
我想编写一个程序,分两步编写一个文件.在程序运行之前,该文件可能不存在.文件名是固定的.
问题是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");
}
Run Code Online (Sandbox Code Playgroud)
She*_*ter 44
fjh绝对正确,但我想更深入地评论一下,并用你的代码触及其他一些错误.
让我们从一个返回引用并查看错误的较小示例开始:
fn try_create<'a>() -> &'a String {
&String::new()
}
Run Code Online (Sandbox Code Playgroud)
锈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 {
| ^^
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
有没有办法从没有参数的函数返回引用?
技术上"是",但对于你想要的,"不".
引用指向现有的内存.在没有参数的函数中,唯一可以引用的是全局常量(具有生命周期&'static)和局部变量.我现在会忽略全局变量.
在像C或C++这样的语言中,您实际上可以引用局部变量并返回它.但是,只要函数返回,就无法保证您引用的内存仍然是您的想法.它可能会保持你期望的一段时间,但最终内存将被重用于其他东西.只要您的代码查看内存并尝试将用户名解释为用户银行帐户中剩余的金额,就会出现问题!
这就是Rust的生命周期所阻止的 - 除了引用值在其当前内存位置有效的时间之外,不允许使用引用.
而不是尝试返回引用,返回拥有的对象.String而不是&str,Vec<T>而不是&[T],T而不是&T等
也可以看看:
查看以下文档OpenOptions::open:
fn open<P: AsRef<Path>>(&self, path: P) -> Result<File>
Run Code Online (Sandbox Code Playgroud)
它返回一个Result<File>,所以我不知道你希望如何返回一个OpenOptions或一个引用.如果你把它重写为:你的功能会起作用:
fn trycreate() -> File {
OpenOptions::new()
.write(true)
.open("foo.txt")
.expect("Couldn't open")
}
Run Code Online (Sandbox Code Playgroud)
这用于Result::expect恐慌并提供有用的错误消息.当然,对程序内容的恐慌并不是非常有用,因此建议将错误传播出去:
fn trycreate() -> io::Result<File> {
OpenOptions::new().write(true).open("foo.txt")
}
Run Code Online (Sandbox Code Playgroud)
Option并Result有很多很好的方法来处理链式错误逻辑.在这里,您可以使用or_else:
let f = OpenOptions::new().write(true).open("foo.txt");
let mut f = f.or_else(|_| trycreate()).expect("failed at creating");
Run Code Online (Sandbox Code Playgroud)
我还返回Result从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(())
}
Run Code Online (Sandbox Code Playgroud)
fjh*_*fjh 16
有没有办法从没有参数的函数返回引用?
否(除了对静态值的引用,但这些对此没有帮助).
但是,您可能想看一下OpenOptions::create.如果您将第一行更改main为
let f = OpenOptions::new().write(true).create(true).open(b"foo.txt");
Run Code Online (Sandbox Code Playgroud)
如果文件尚不存在,将创建该文件,这将解决您的原始问题.
引用是指针。一旦函数被执行,它们就会从执行堆栈中弹出并且资源被取消分配。
对于以下示例,x在块的末尾删除。在那之后,引用&x将指向一些垃圾数据。基本上它是一个悬空指针。Rust 编译器不允许这样的事情,因为它不安全。
fn run() -> &u32 {
let x: u32 = 42;
return &x;
} // x is dropped here
fn main() {
let x = run();
}
Run Code Online (Sandbox Code Playgroud)
这是对snnsnn 的回答的详细说明,它简要地解释了问题,但不太具体。
Rust 不允许返回对在函数中创建的变量的引用。有解决方法吗?是的,只需将该变量放在一个Box 中然后返回它。例子:
fn run() -> Box<u32> {
let x: u32 = 42;
return Box::new(x);
}
fn main() {
println!("{}", run());
}
Run Code Online (Sandbox Code Playgroud)
根据经验,为了避免 Rust 中的类似问题,返回一个拥有的对象(Box、Vec、String 等)而不是对变量的引用:
Box<T> 代替 &TVec<T> 代替 &[T]String 代替 &str对于其他类型,请参阅Rust 类型周期表以找出要使用的拥有对象。
当然,在这个例子中你可以简单地返回值(T而不是&Tor Box<T>)
fn run() -> u32 {
let x: u32 = 42;
return x;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
12957 次 |
| 最近记录: |