arrays - 为什么 Rust 中作为参数传递的 &str 数组具有不同的生命周期?
问题描述
我正在学习 Rust 并且正在通过函数测试一些数组复制。我确信有内置的 Rust 函数来复制/克隆数组信息,但我认为个人实现将是一个好主意,可以帮助我理解通过函数传递引用。
fn copy_str_arr_original (a1: [&str; 60], a2: &mut [&str; 60]) {
// copy 1 into 2
for i in 0..60 {
a2[i] = a1[i];
} // change is reflected in a2 as it is passed as &mut
}
但是,这引发了these two types are declared with different lifetimes...
类型&str
本身的错误。经过一些进一步的研究,我尝试宣布自己的生命并将其分配给它,并且解决了它!
fn copy_str_arr_fix<'a> (a1: [&'a str; 60], a2: &mut [&'a str; 60]) {
// copy 1 into 2
for i in 0..60 {
a2[i] = a1[i];
} // change is reflected in a2 as it is passed as &mut
}
为什么会这样呢?为什么需要为数组中的值类型而不是参数本身分配生命周期?换句话说,为什么这根本不起作用?
fn copy_str_arr_bad<'a> (a1: &'a [&str; 60], a2: &'a mut [&str; 60]) {
// does not work... ^-----------------------^-------- different lifetimes
for i in 0..60 {
a2[i] = a1[i];
}
}
我仍在努力了解生命周期如何在更复杂的对象(如数组和结构)的上下文中工作,所以任何解释都将不胜感激!
解决方案
错误消息有点令人困惑,因为它指的是根据生命周期省略规则生成的生命周期。在您的情况下,终身省略意味着:
fn copy_str_arr_original(a1: [&str; 60], a2: &mut [&str; 60])
是语法糖:
fn copy_str_arr_original<'a1, 'a2_mut, 'a2>(a1: [&'a1 str; 60], a2: &'a2_mut mut [&'a2 str; 60])
换句话说,我们有三个完全不相关的生命周期。“不相关”意味着调用者可以选择与它们关联的对象的生存时间。例如,in 中的字符串a2
可能是静态的并且一直存在到程序结束,而 in 中的字符串可能在返回a1
后立即被删除。copy_str_arr_original()
或者反过来。如果这种自由度看起来可能会导致问题,那么您就在正确的轨道上,因为借用检查器同意您的看法。
请注意,有点违反直觉,'a2_mut
生命周期的长度完全无关紧要,它可以与调用者一样长或短。我们的函数已收到引用,因此可以在函数范围内使用它。'a2_mut
生命周期告诉我们它将在函数范围之外存在多长时间,我们只是不关心这一点。
'a1
'a2
是另一回事。由于我们从a1
to复制引用a2
,因此我们有效地将(类型)内部的引用转换为存储在(即)中的引用类型:a1
&'a1 str
a2
&'a2 str
a2[i] = a1[i]; // implicitly casts &'a1 str to &'a2 str
要使其有效,&'a1 str
必须是 的子类型。&'a2 str
虽然 Rust 没有 C++ 意义上的类和子类,但它确实有涉及生命周期的子类型。从这个意义上说,如果 A 值的值保证至少与 B 的值一样长,则 A 是 B 的子类型。换句话说,'a1
必须至少与 一样长'a2
,表示为'a1: 'a2
。所以编译:
fn copy_str_arr<'a1: 'a2, 'a2, 'a2_mut>(a1: [&'a1 str; 60], a2: &'a2_mut mut [&'a2 str; 60]) {
for i in 0..60 {
a2[i] = a1[i];
}
}
演员表成功的另一种方法是只要求生命周期与您在copy_str_arr_fix()
. (您还省略了'a2_mut
生命周期,编译器将其正确解释为对不相关的匿名生命周期的请求。)
推荐阅读
- java - LinkedList 临时头更新原始头
- arrays - 给定字符串数组动态初始化结构
- linux - 如何在日志中的每一行之前记录时间戳?
- facebook-marketing-api - 在沙盒帐户中使用 Facebook 营销 API 创建广告时出错
- java - com.fasterxml.jackson.databind.exc.InvalidDefinitionException:无法构造`org.springframework.web.multipart.MultipartFile`的实例
- xaml - 如何禁用 UWP 应用的缩放
- java - 如何返回两个对象的差异
- sql - 有没有办法可以将Oracle中每个表的序列的last_number字段设置为该表主键的最大值?
- django - 如何提取 django 表单字段?
- kubernetes - 我们可以从两个现有的 Yamls 中创建一个 POD,每个 Yamls 都有自己的容器吗?