compiler/fight-with-compiler/lifetime/too-long1 #981
Replies: 4 comments 1 reply
-
可不可以这人认为:结构体里,尽量不要用引用,比如&str,用String并不会浪费什么资源,却可以让代码更清楚、更快速开发。 |
Beta Was this translation helpful? Give feedback.
-
是否可以这样说,凡是文中Interface结构体这种类型的代码,最佳实践都应该是样: |
Beta Was this translation helpful? Give feedback.
-
这里说方法的声明周期是很困惑的事情。返回的interface在方法中,需要比List结构体实例活得长,但是返回的Interface 变了又占用了对List的可变访问。 |
Beta Was this translation helpful? Give feedback.
-
写了一篇解析:https://blog-blockchain.xyz/dev/rust-lifetime/ 生命周期规则我们先了解这里约束的是什么,建议直接去看英文原版的官方写的rust book。生命周期是变量从创建到销毁的有效区间。
生命周期还有3条推导规则。注意术语: input lifetimes和output lifetimes,表示参数和返回值。
循环引用https://course.rs/compiler/fight-with-compiler/lifetime/too-long1.html 这个例子最大的特殊点在于,我们平常都是函数、结构体、方法中引用数据的生命周期是单独介绍的。但是这里搞复杂了,增加了各种奇怪的约束,比如说我们看一些组合起来的写法。 impl<'a> List<'a> {
pub fn get_interface(&'a mut self) -> Interface<'a> {
// ...
}
} 在方法中 pub fn get_interface(&'a mut List<'a> input) -> Interface<'a> {
// ...
} 对于这种写法,混合了结构体的生命周期约束和函数参数的生命周期约束。可以叫做「生命周期绑定」或者叫做「生命周期纠缠」,编译器认为这个借用永远不会结束。表示
写代码需要有一个原则,避免引用循环,类似 struct Interface<'b,'a> {
manager: &'b mut Manager<'a>
}
impl<'a> List<'a> {
pub fn get_interface(&mut self) -> Interface {
// ...
}
} 但是根据规则3, impl<'a> List<'a> {
pub fn get_interface<'b>(&'b mut self) -> Interface<'b,'b> {
Interface {
manager: &mut self.manager
}
}
} 但是因为创建的Interface使用到了 impl<'a> List<'a> {
pub fn get_interface<'b>(&'b mut self) -> Interface<'b,'a> {
Interface {
manager: &mut self.manager
}
}
} 最终建议再次强调,不要可变引用循环,类似
不可变的循环引用,是可以的。比如改动 struct Interface,去掉 struct Interface<'a> {
manager: &'a Manager<'a>
}
impl<'a> Interface<'a> {
pub fn noop(self) {
println!("interface consumed");
}
}
struct Manager<'a> {
text: &'a str
}
struct List<'a> {
manager: Manager<'a>,
}
impl<'a> List<'a> {
pub fn get_interface(&'a self) -> Interface {
Interface {
manager: &self.manager
}
}
}
fn main() {
let mut list = List {
manager: Manager {
text: "hello"
}
};
list.get_interface().noop();
println!("Interface should be dropped here and the borrow released");
// this fails because inmutable/mutable borrow
// but Interface should be already dropped here and the borrow released
use_list(&list);
}
fn use_list(list: &List) {
println!("{}", list.manager.text);
} 也要避免可变引用的传递 第三种,下面的例子也是可变循环引用。m1类型是 struct S<'a> {
i: i32,
r: &'a i32,
}
let mut s = S { i: 0, r: &0 };
let m1 = &mut s;
m1.r = &m1.i; // 此时s.r引用了s.i,创建了自引用 参考:https://stackoverflow.com/a/66253247/18309513 以及它提到的回答。 |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
compiler/fight-with-compiler/lifetime/too-long1
https://course.rs/compiler/fight-with-compiler/lifetime/too-long1.html
Beta Was this translation helpful? Give feedback.
All reactions