Rust 官方例子生命周期注解疑惑

fn main() {
    let string1 = String::from("long string is long");

    {
        let string2 = String::from("xyz");
        let result = longest(string1.as_str(), string2.as_str());
        println!("The longest string is {}", result);
    }
}

fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

这是这里的一个例子 rust book,代码自上而下执行,在调用 longest 时,string1 跟 string2 都是传递有效的引用,而且会进入longest 函数里面执行,那既然都是有效的引用,那么函数接收的也是有效的,为何会无法确定生命周期?或者说为啥要确定生命周期?

rust 折磨我千百遍,我却待它如初恋,望大佬解答!

阅读 3.1k
3 个回答

在Rust中所有引用类型的参数都存在独立的生命周期,例如'a, 'b等。
在不进行显式生命周期标注的情况下。编译器进行的生命周期标注为:

fn longest(x: &'a str, y: &'b str) -> &str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

此时编译器无法针对返回值的生命周期做出正确的标注。故而,需要显示的进行生命周期标注。

有一些默认的规则,是不需要显式标注的:

  • 如果只有一个引用类型输入,它的生命周期会赋给所有输出
  • 如果有多个引用类型的参数,其中一个是self,那么它的生命周期会赋给所有输出

参考:生命周期:你创建的值究竟能活多久?

我是前端开发者,说一下我的感受: Rust比其他的GC类型的语言难一点; 难点是:所有权,生命周期等概念;而其他的概念和其他语言基本一样。 希望更多的朋友关注rust
为什么需要确定生命周期

为了尽量确保不会出现:悬垂指针,2次释放等问题; 生命周期只是在编译时进行检查;程序运行时和C/C++一样没有生命周期的概念。 对于显而易见 或者符合一定规律的方法是可以省略声明周期参数 这些规则也可以在the book中看到哈;对于有些复杂的情况就需要 显示声明声明周期

再来看一下 The book 中第二个例子 ;在这个例子中按照一般程序的创建释放时间来理解也可以看出会发生悬垂引用, 而rust中引入生命周期这个检查机制来尽量避免此类问题的发生;

fn main() {
    let string1 = String::from("long string is long");
    let result;
    {
        let string2 = String::from("xyz");
        result = longest(string1.as_str(), string2.as_str());
    }
    println!("The longest string is {}", result);
}
我感觉不错的学习资料
  • learn rust by example 也有对应的中文版哈
  • Rust程序设计;不过现在最新第2版只有英文版: Programming Rust, 2nd Edition;
  • the book 也有对应中文版

如果英文能力强直接看英文; 次之建议:中英结合进行学习

调用 longest 时,string1 跟 string2 都是传递有效的引用,

问题就在这。rust 的检查时在编译期进行的,谁调用了它,怎样调用的,等等的信息都是运行时才能知道的信息。在编译期,要保证无论谁调用了它,无论怎么怎么调用的,无论传递的参数是什么,都要可以正常推断。但是,如果没有标注,编译器无法推断返回值的声明周期(是 x 的,还是 y 的?在调用时,x 与 y 的声明周期不一定是相同的),所以后续对返回值的所有判断都无法进行。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题