今天和朋友交流的时候遇到了自引用问题,之前就在看 Rust Bible 的时候看到过,但是一直没用 Rust 写过什么数据结构,所以没有使用这个的机会,所以今天就来尝试一下。
首先需要实现的结构体如下:
struct Person {
name: String,
first_name: &str,
last_name: &str,
}
这里的 first_name
和 last_name
的生命周期应该短于 name
和整个结构体的生命周期。这里使用不同的生命周期标注其实意义不大,它怎么也不能在一个函数中成功创建并返回。因为想要生成一个 slice 必须借用一个 String ,但当这个 String 被 move 进入 Person
结构体时,与之相关的 slice 全部失效了。
所以软的不行只能来硬的,直接使用 unsafe
:
#[derive(Debug)]
#[allow(unused)]
struct Person<'a> {
name: String,
first_name: &'a str,
last_name: &'a str,
}
impl<'a> Person<'a> {
fn new(s: String) -> Person<'a> {
let (first, last) = match s.find(' ') {
Some(pos) => {
s.split_at(pos)
}
None => {
(s.as_str(), s.as_str())
}
};
let first = first as *const str;
let last = last as *const str;
unsafe {
Person { name: s, first_name: &*first, last_name: &*last }
}
}
}
fn main() {
let p = Person::new("Linus Torvalds".to_string());
println!("{:?}", p);
}
先将引用转成 raw point ,这就避免了它在 ponitee 被移动后失效。之后直接使用 unsafe ,再将指针转成引用即可。
虽然很蛋疼,但这就是 Rust ,Love it or leave it!