您的位置:首页 > 新闻 > 热点要闻 > 九江网站建设制作_网络舆情监控_佛山网站优化服务_中国疾控卫生应急服装

九江网站建设制作_网络舆情监控_佛山网站优化服务_中国疾控卫生应急服装

2025/1/8 18:59:42 来源:https://blog.csdn.net/weixin_71793197/article/details/144938555  浏览:    关键词:九江网站建设制作_网络舆情监控_佛山网站优化服务_中国疾控卫生应急服装
九江网站建设制作_网络舆情监控_佛山网站优化服务_中国疾控卫生应急服装

喜欢的话别忘了点赞、收藏加关注哦,对接下来的教程有兴趣的可以关注专栏。谢谢喵!(=・ω・=)
请添加图片描述

10.6.1. 生命周期标注语法

  • 生命周期的标注并不会改变引用的生命周期长度。
  • 如果某个函数它制定了泛型生命周期参数,那么它就可以接收带有任何生命周期的引用。
  • 生命周期的标准主要是用于描述多个引用的生命周期之间的关系,但不影响生命周期。

生命周期的参数名称必须以'开头,通常是全小写且非常短的。很多开发者使用'a作为生命周期参数的名称。

生命周期的标注放在&符号后,在标注后边使用空格将标注和引用类型分开。

10.6.2. 生命周期标注例子

  • &i32:一个普通的引用
  • &'a i32:带有显式生命周期的引用,引用指向的类型就是i32
  • &'a mut i32:带有显式生命周期的可变引用

单个生命周期的标注本身没有意义,生命周期标注存在的意义是向Rust描述多个泛型生命周期之间的参数的关系。

以上一篇文章的代码为例:

fn main() {  let string1 = String::from("abcd");  let string2 = "xyz";  let result = longest(string1.as_str(), string2);  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  }  
}

longest中的形参xy以及返回值的生命周期都是'a,这就意味着xy和返回值必须拥有“相同的”生命周期。

通过刚才的代码例也看到了,在函数签名中使用生命周期标注需要把泛型生命周期参数生命在<>里。这个签名会告诉Rust有这么一个生命周期'a,而xy和返回值的存活时间必须不短于'a

因为生命周期的标准主要是用于描述多个引用的生命周期之间的关系,但不影响生命周期。 所以这么写并不会影响实参的生命周期,这样写只是为借用检查器指出了一些可用于检查非法调用的一些约束而已。所以longest函数并不需要知道xy具体的存活时长,只需要某个作用域可以被用来代替'a,同时满足函数的签名约束即可。

如果函数引用它外部的代码,或者说它被外部的代码引用的时候,想单靠Rust本身来确定参数和返回值的生命周期几乎就是不可能的了。这样函数所使用的生命周期可能在每次调用中都发生变化。正是因此才需要手动对生命周期进行标注

在代码例中,当我们把具体的引用传入longest函数的时候,被用来代替'a的生命周期的作用域是哪一块呢?就是x的作用域和y的作用域所重叠的部分,也就是两者中生命周期较短的那个的生命周期。又因为返回值的生命周期也是'a,所以说返回的引用在x的作用域和y的作用域所重叠的部分都是有效的。

这就是为什么在前一篇文章和本文的前面对于“相同的”这个词都使用了引号标注,因为它并不是字面意义上的相同,而是指重叠的部分。

下面来看一下生命周期标注是如何对longest函数调用进行限制的。如果我们改一下上边的代码例,把string1的作用域改并把string2改为String类型会怎么样:

fn main() {  let string1 = String::from("abcd");  {  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  }  
}

这样string1的作用域是从第2行到第8行,string2的作用域是从第4行到第7行。函数会寻找重叠的部分(或者说较短的那个生命周期),也就是string2的作用域第4行到第7行,所以'a指代的作用域就是第4行到第7行。result在内部作用域,也就是花括号结束之前(第7行)一直有效,在'a的作用域内,所以代码仍然有效。

那如果我改变result的作用域呢:

fn main() {  let string1 = String::from("abcd");  let result;  {  let string2 = String::from("xyz");  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  }  
}

这个时候string1的作用域是从第2行到第9行,string2的作用域是从第5行到第7行,将这两者传入longest,函数会寻找重叠的部分(或者说较短的那个生命周期),也就是string2的作用域第5行到第7行,所以函数的泛型作用域参数'a就是第5行到第7行,那么返回值的作用域也该是第5行到第7行。但是用于接收返回值的result变量的作用域实际是第3行到第9行,超出了'a指代的作用域,所以程序会报错:

error[E0597]: `string2` does not live long enough--> src/main.rs:6:44|
5 |         let string2 = String::from("xyz");|             ------- binding `string2` declared here
6 |         result = longest(string1.as_str(), string2.as_str());|                                            ^^^^^^^ borrowed value does not live long enough
7 |     }|     - `string2` dropped here while still borrowed
8 |     println!("The longest string is {result}");|                                     -------- borrow later used here

编译器会提示string2的存活时间不够。为了保证第8行的打印的result有效,那么string2必须在外部作用域结束之前一直保持有效。因为函数的参数和返回值是用了相同的生命周期,所以Rust才会指出这个问题。

最后再重复一遍这篇文章最重要的知识点:生命周期'a的实际生命周期是取xy两个生命周期中较小的那个。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com