gpt4 book ai didi

rust - 为什么这不是一个悬空指针?

转载 作者:行者123 更新时间:2023-12-04 11:52:18 25 4
gpt4 key购买 nike

我正在研究 Rust 书,它有 this code snippet :

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()
}
上一章已经说明
  • Rust 编译器会阻止您在对象超出范围(悬空引用)后将引用保留到对象中,并且
  • 变量在它们被提及的最后一刻超出范围(给出的示例显示了在同一块中创建对同一对象的不可变和可变引用,确保在创建后不提及不可变引用可变引用)。

  • 对我来说,它看起来像 bytesfor 之后没有被引用行头(大概与 bytes.iter().enumerate() 相关的代码在循环开始前只执行一次,而不是在每次循环迭代中),所以 &item不应该被允许作为对 bytes 任何部分的引用.但是我没有看到任何其他对象(“对象”是正确的 Rust 术语吗?)它可以作为引用。
    确实如此 s仍在范围内,但是,嗯……编译器是否还记得 bytes 之间的连接?和 s到时候 for循环滚动?确实,即使我将函数更改为接受 bytes直接,编译器认为事情是笨拙的:
    fn first_word(bytes: &[u8]) -> usize {
    for (i, &item) in bytes.iter().enumerate() {
    if item == b' ' {
    return i+1;
    }
    }

    0
    }
    这里除了 i 没有其他变量或 itemfor 之后提到循环标题,所以它真的看起来像 &item不能作为任何东西的引用!
    我看了 this very similarly-titled question .那里的评论和答案表明,可能存在一个终生的争论,即 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
    }
    但是,错误,同时确实表明 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]`
    那么这里发生了什么?显然,我的推理的某些部分是错误的,但是什么?为什么不是 item悬空引用?

    最佳答案

    这是第一个函数的版本,包含所有生命周期和类型,以及 for循环替换为等效的 while let环形。

    fn first_word<'a>(s: &'a String) -> usize {
    let bytes: &'a [u8] = s.as_bytes();

    let mut iter: std::iter::Enumerate<std::slice::Iter<'a, u8>>
    = bytes.iter().enumerate();

    while let Some(iter_item) = iter.next() {
    let (i, &item): (usize, &'a u8) = iter_item;
    if item == b' ' {
    return i;
    }
    }

    s.len()
    }
    这里需要注意的事项:
  • bytes.iter().enumerate()产生的迭代器的类型有一个生命周期参数来确保迭代器的生命周期不会超过 [u8]它迭代。 (请注意, &[u8] 可以消失——不需要它。重要的是它的所指对象,即 String 中的字节,仍然活着。所以,我们真的只需要考虑一个生命周期 'asbytes 的生命周期没有分开,因为在 String 中只有一个 byte slice ,我们用不同的方式来指代它。
  • iter — 与 for 的隐式操作相对应的显式变量— 用于循环的每次迭代。

  • 我看到另一个误解,不完全是关于生命周期和范围:

    there might be a lifetime argument which is keeping bytes alive,


    一生永远不会让某些东西活着。 生命周期永远不会影响程序的执行;它们永远不会影响某些东西何时被丢弃或解除分配。某种类型的生命周期,例如 &'a u8是一个编译时声明,该类型的值将在该生命周期内有效。更改程序中的生命周期仅更改编译器要证明(检查)的内容,而不更改程序的真实内容。

    关于rust - 为什么这不是一个悬空指针?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69016205/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com