时长:大小12.94M
作者回复: &str 不是静态区域内存的指针。&str 是一个字符串切片,一个带有长度的胖指针,指向字符串实际的位置。它可以指向 "hello world",此时指针指到了 RODATA/STRING section 里 "hello" 的地址,它的生命周期是 'static;也可以指向 "hello world".to_string(),此时指针指向了这个字符串的堆地址,生命周期是 'a。
作者回复: 👍
作者回复: 1. 好问题。还是要从生命周期中参数和返回值的关系来看,因为现在我们把对字符串的可变引用的生命周期和返回值的生命周期关联起来了,hello 得到了 strtok 的返回值,所以从编译器看来,&mut s1 的生命周期并没有结束,所以发生了 &mut 和 & 同时存在的局面。 2. 👍 3. 赞 4. 我觉得这是个翻译风格问题,从字面意思上看生命期更好,但大家最惯用的说法已经约定俗称,而且不光 Rust,其它语言在谈到 lifetime 时也是如此(比如 react),所以生命周期更好。它起码比福尔摩斯的译名要好吧 lol。 5. 不会。生命周期在单体化之前就会被处理掉。它更多以编译器的错误呈现出来。对编译器来说,只要满足约束,更长的生命周期的变量也可以通过编译(比如 &'static str 至于 &'a str)。如果生命周期做单体化,下面的代码就可以编译,然而不行: ```rust trait Print { fn print(self); } // 生命周期无法像泛型那样有多个实现 // impl<'a> Print for &'a str { // fn print(self) { // println!("Arbitrary str: {}", self); // } // } impl Print for &'static str { fn print(self) { println!("'static str: {}", self); } } // 也无法单体化 fn print_str<'a>(s: &'a str) { s.print() } fn main() { let s = "hello, world!"; s.print(); print_str(s); } ``` playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=b767ef1a9d9e265252c1ad29d31176b0
作者回复: 👍
作者回复: 1. 正确! 2. 好问题,理论上可以,但编译器目前没有做这样的事情,主要是代码可读性的担忧。可以看:https://github.com/rust-lang/rfcs/blob/master/text/0141-lifetime-elision.md#lifetime-elision-in-structs。
作者回复: 对! 的确,在不是特别理解 &mut &str 在内存中的意义时容易出错,我们需要知道它是一个指向字符串引用的可变指针。这样,返回值和谁产生约束就一目了然了。
作者回复: 👍
作者回复: 👍
作者回复: 对
作者回复: 这样并不理想。因为 strtok 并不想改变原有的字符串,只是改变指向这个字符串的可变引用。
作者回复: 一个引用一个生命周期
作者回复: 👍
作者回复: 'a 代表的是一个泛化的生命周期,表示我支持任何长度的生命周期。比如: fn max<'a, 'b: 'a>(s1: &'a str, s2: &'b str) -> &'a str {} 表明 'a 和 'b 可能是不同的生命周期,'b 生命周期大于等于 'a。返回值需要满足 'a 的生命周期。整个函数相当于在说,给定两个参数,返回值的生命周期要大于这两个参数中小的那个。 所以函数参数的生命周期是一种约束,而不是一个具体的值。它本身就可以随着传入的生命周期而自适应,只要它们满足约束就可以。你可以好好理解一下下面的代码: ```rust fn max<'a, 'b: 'a>(s1: &'a str, s2: &'b str) -> &'a str { s1 } fn main() { let s1 = String::from("hello"); let s2 = String::from("world"); // 静态 let s3 = "hello"; let s4 = "world"; max(&s1, &s2); max(&s1, s3); max(s3, s4); max(&s1, s3); // 这里 s3 是 'static,s1 是 'b,s3 传入后会降级成 'a,它依旧满足 'b: 'a 的约束 max(s3, &s1); } ``` playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=0080b95b36db1674b5d4d4c29793b1ab
作者回复: 对于 1,你可以再看看我文中画的图,好好感受一下 &mut &str 表示什么。&str 是一个字符串切片,&mut &str 是指向这个字符串切片的一个可变的引用。所以我们的问题是:返回值的生命周期究竟应该是和字符串切片有关?还是跟对这个字符串切片的可变引用有关?
作者回复: 当 Rust 编译器不能标注生命周期需要开发者进行标注时,一定是编译器无法从已知的逻辑中找到参数和返回值之间的关系。所以我们要说明这种关系。 我们可以说 s1, s2 生命周期一致,返回值和他们的一致。这是我文中代码的表述。 也可以说 s1, s2 生命周期不一致,我们返回值的生命周期是比较小的那个。这是这段代码的表述。