Rust:这里为什么不用写成生命周期?

这里为什么不用写成生命周期?
我在看教程的时候看到生命周期,然后回看前面的教程:
When I read the tutorial, I see the Lifetime chapter, and then look back at the previous chapter .There is one of that sample code:

fn main() {
    let s1 = String::from("hello");

    let len = calculate_length(&s1);

    println!("The length of '{}' is {}.", s1, len);
}

fn calculate_length(s: &String) -> usize {
    s.len()
}

这里的calculate_length引用和usize为什么可以不要求以生命周期'a的形式去声明?而且这里也不会报错。
Why can calculate_length and usize not be declared in the form of lifetime **'a** ? And there will be no error here.
我看生命周期的教程时都要写成类似于这样:
When I read the lifetime tutorial, I should write something like this:

fn longer<'a>(s1: &'a str, s2: &'a str) -> &'a str {
    if s2.len() > s1.len() {
        s2
    } else {
        s1
    }
}

=======================================================
补充:
有人说上面那个参数是1个,下面那个参数是2个,所以上面不会报错,然后我试了一下上面改成2个参数,一样没问题可以编译通过,不用修改成生命周期:

fn main() {
    let s1 = String::from("hello");
    let s2 = String::from("hello");

    let len = calculate_length(&s1,&s2);

    println!("The length of '{}' is {}.", s1, len);
}

fn calculate_length(s: &String,k:&String) -> usize {
    s.len()
    // .try_into().unwrap()
}

一样正常输出The length of 'hello' is 5.而不用添加生命周期。

所以到底是为什么?

阅读 2.5k
1 个回答

问题 1:

fn main() {
    let s1 = String::from("hello");

    let len = calculate_length(&s1);

    println!("The length of '{}' is {}.", s1, len);
}

fn calculate_length(s: &String) -> usize {
    s.len()
}

这里的calculate_length引用和usize为什么可以不要求以生命周期'a的形式去声明?而且这里也不会报错。

答:

首先 引用(references) 才有生命周期的概念(Rust has a feature for using a value without transferring ownership, called references and every reference in Rust has a lifetime), 而usize不是引用,所以不需标注生命周期,平台不同它实际值也不同可能是u32或者u64或者其他

根据生命周期省略规则(lifetime elision rules) 编译器为每一个是引用参数都分配了一个生命周期参数,上面函数 calculate_length 的完整签名应该是下面这样,

fn calculate_length<'a>(s: & <'a>String) -> usize {
    s.len()
}

生命周期的标注由编译器自动添加了

问题 2:

下面有2个参数,一样没问题可以编译通过,不用修改成生命周期:

fn main() {
    let s1 = String::from("hello");
    let s2 = String::from("hello");

    let len = calculate_length(&s1,&s2);

    println!("The length of '{}' is {}.", s1, len);
}

fn calculate_length(s: &String,k:&String) -> usize {
    s.len()
    // .try_into().unwrap()
}

答 :

根据生命周期省略规则(lifetime elision rules) 编译器为每一个是引用参数都分配了一个生命周期参数,而不论有多少个参数, usize不是引用,所以无需生命周期标注,calculate_length 的完整签名应该是下面这样,


fn calculate_length<'a,'b>(s: & 'a String,k:& 'b String) -> usize {
    s.len()
    // .try_into().unwrap()
}

下面是给出的英文生命周期省略规则地址 :lifetime-elision

其他可以参考的内容 what-is-ownership, references-and-borrowing , 当然也有其他相应的中文翻译可参考;

Other

虽然有些咬文嚼字,希望下面能回答什么是 borrowing

fn calculate_length(s: &String) -> usize { // s is a reference to a String
    s.len()
} // Here, s goes out of scope. But because it does not have ownership of what
  // it refers to, it is not dropped.

The scope in which the variable s is valid is the same as any function parameter’s scope, but the value pointed to by the reference is not dropped when s stops being used, because s doesn’t have ownership. When functions have references as parameters instead of the actual values, we won’t need to return the values in order to give back ownership, because we never had ownership.

We call the action of creating a reference "borrowing" . As in real life, if a person owns something, you can borrow it from them. When you’re done, you have to give it back. You don’t own it.

https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html

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