我正在研究 Rust 书,它有以下代码片段:
fn first_word(s: &String) -> usize {
let bytes = s.as_bytes();
for (i, &item) in bytes.iter().enumerate() {
if item == b' ' {
return i;
}
}
s.len()
}
Run Code Online (Sandbox Code Playgroud)
上一章已经说明
对我来说,它看起来在行头bytes之后没有被引用for(大概是关联的代码bytes.iter().enumerate()在循环开始前只执行一次,而不是在每次循环迭代中),所以&item不应该被允许成为bytes. 但是我没有看到任何其他对象(“对象”是正确的 rust 术语吗?)它可以作为参考。
确实,这s仍然在范围内,但是,好吧......编译器甚至记得循环滚动时bytes和之间的连接吗?确实,即使我将函数更改为直接接受,编译器也会认为事情很糟糕:sforbytes
fn first_word(bytes: &[u8]) -> usize {
for (i, &item) in bytes.iter().enumerate() {
if item == b' ' {
return i+1;
}
}
0
}
Run Code Online (Sandbox Code Playgroud)
这里除了循环头之后没有提到i或之外的任何变量,所以它似乎真的不能作为任何东西的引用!itemfor&item
我看了这个标题非常相似的问题。那里的评论和答案表明可能有一个生命周期参数保持bytes活跃,并提出了一种方法来询问编译器它认为类型/生命周期是什么。我还没有了解生命周期,所以我在黑暗中摸索了一下,但我尝试过:
fn first_word<'x_lifetime>(s: &String) -> usize {
let bytes = s.as_bytes();
let x_variable: &'x_lifetime () = bytes;
for (i, &item) in bytes.iter().enumerate() {
if item == b' ' {
return i+1;
}
}
0
}
Run Code Online (Sandbox Code Playgroud)
但是,该错误虽然确实表明bytes是&[u8],但我理解,似乎也暗示没有与bytes. 我这样说是因为错误包括“预期”部分中的生命周期信息,但不包括“发现”部分中的生命周期信息。这里是:
error[E0308]: mismatched types
--> test.rs:3:39
|
3 | let x_variable: &'x_lifetime () = bytes;
| --------------- ^^^^^ expected `()`, found slice `[u8]`
| |
| expected due to this
|
= note: expected reference `&'x_lifetime ()`
found reference `&[u8]`
Run Code Online (Sandbox Code Playgroud)
那么这里发生了什么?显然,我的推理的某些部分是错误的,但是什么?为什么不是item悬空引用?
这是第一个函数的版本,其中包含所有生命周期和类型,并将for循环替换为等效while let循环。
fn first_word<\'a>(s: &\'a String) -> usize {\n let bytes: &\'a [u8] = s.as_bytes();\n\n let mut iter: std::iter::Enumerate<std::slice::Iter<\'a, u8>>\n = bytes.iter().enumerate();\n\n while let Some(iter_item) = iter.next() {\n let (i, &item): (usize, &\'a u8) = iter_item;\n if item == b\' \' {\n return i;\n }\n }\n\n s.len()\n}\nRun Code Online (Sandbox Code Playgroud)\n这里需要注意的事项:
\nbytes.iter().enumerate()有一个生命周期参数,该参数确保迭代器的寿命不会超过它[u8]迭代的时间。(请注意,&[u8] 可以消失 \xe2\x80\x94\xc2\xa0it 不是必需的。重要的是它的所指对象,即内的字节String,保持活动状态。因此,我们只需要考虑一个生命周期\'a,s和没有单独的生命周期,因为我们以不同方式引用的bytes内部只有一个字节片。Stringiter\xe2\x80\x94\xc2\xa0 与 \xe2\x80\x94 的隐式操作相对应的显式变量在循环的每次迭代中for使用。我看到另一个误解,不完全是关于生命周期和范围的:
\n\n\n可能会有终生的争论持续存在
\nbytes,
一生永远不会让某些东西活着。生命周期永远不会影响程序的执行;它们永远不会影响某些东西被丢弃或释放的时间。某些类型的生命周期&\'a u8是编译时声明,该类型的值将在该生命周期内有效。更改程序中的生命周期只会更改编译器要证明(检查)的内容,而不更改程序的真实情况。
| 归档时间: |
|
| 查看次数: |
97 次 |
| 最近记录: |