今天和朋友交流的时候遇到了自引用问题,之前就在看 Rust Bible 的时候看到过,但是一直没用 Rust 写过什么数据结构,所以没有使用这个的机会,所以今天就来尝试一下。

首先需要实现的结构体如下:

struct Person {
    name: String,
    first_name: &str,
    last_name: &str,
}

这里的 first_namelast_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!