【问题标题】:Explanation on References and Borrowing from The Rust bookThe Rust book 的参考和借用说明
【发布时间】:2019-06-22 16:19:41
【问题描述】:

我正在阅读 Rust 书,第 4 章中的参考和借用似乎与我不一致。 在Reference and Borrowing中,下图4-5显示s指向s1而不是堆上的实际数据。

fn main() {
    let s1 = String::from("hello");

    let len = calculate_length(&s1);

    println!("The length of '{}' is {}.", s1, len);
}

fn calculate_length(s: &String) -> usize {
    s.len()
}

但在String Slices 中,图表清楚地表明world 引用了实际数据,尽管只是其中的一部分。它还说,以下代码“类似于引用整个字符串,但带有额外的 [0..5] 位。它不是对整个字符串的引用,而是对字符串的一部分的引用。”

fn main() {
    let s = String::from("hello world");

    let hello = &s[0..5];
    let world = &s[6..11];
}

下面是解释上述代码的图表(图 4-6):

现在我想我的问题是为什么 world 在 String Slices 案例中不指代 s?我知道world 不能只指向s,因为那样它就无法获取最后5 个字母。但这两张图在我看来完全不同,但它们都是“参考”。有人可以提供一个合乎逻辑的方式来理解它吗?

谢谢!

【问题讨论】:

    标签: rust


    【解决方案1】:

    那么,&[mut] String 在安全上下文中保证什么?

    • 指针后面有一个String,因此支持您的第一个图表。

    那么,&[mut] str 在安全上下文中保证什么?

    • String 的想法相同,在指针后面有一个str。但是,这是什么意思? str 到底是什么?

    根据文档页面:

    &str 由两部分组成:指向某些字节的指针和长度。

    意思是,&str 确实是指向某个有效 utf-8 和长度的指针,所以实际上,str 是数据本身,不是StringString 可视为可操作的str。所以&my_string[..]实际上是String下数据的指针/引用。

    【讨论】:

    • 感谢乐观桃子。我想我明白你在说什么。所以我可以这样理解吗:&s[0..5] 首先将 s[0..5] 获取为str,在本例中为“世界”字符串,然后使用 & 获取指向的指针/引用是吗?
    • 我不太明白你想说什么,String&str 都指的是相同的数据,只是恰好是 &str 指向直接获取数据,而不是通过String,而String实际上拥有内部str
    • 我明白String&str 都指的是相同的数据。我想我很难理解的是当你说“它只是 碰巧&str 直接指向数据”时的部分,因为在第一个图中它显示 &String 指向到String,但在第二个示例中,s 仍然是String,唯一不同的是示例使用了&s[0..5],我的理解是您将&s[0..5] 视为&str,这导致我理解s[0..5] 返回一个str,然后我们使用& 来引用它。谢谢:p
    • 好吧,我想我错了。我在想&s[0..5] 中有操作优先级,但显然情况并非如此。当sString 时,我不能做s[0..5]。所以&s[0..5] 必须同时发生并返回一个&str,就像你说的,恰好&str 直接指向数据(可能是设计选择)。
    • 是的,s[..] 相当于str,因为str 是实际数据,str 和构成数据的原始连续字节之间没有分隔,但它必须保留在指针后面,因为它没有已知大小,因此不能存在于堆栈中,Stringstr 上的“智能”指针,可以重新分配和更改大小
    【解决方案2】:

    对字符串的引用和字符串切片是不同的东西,所以它们的表示不同是正常的。

    大多数情况下,字符串切片更有用,因为您可以引用子字符串,这使其更加灵活。一般来说,读取一些字符串数据的函数参数应该是字符串切片,而不是对字符串的引用。

    另外,you can use an actual parameter of type &String for a string slice:

    字符串实现了 Deref,因此继承了所有 str 的 方法。此外,这意味着您可以将 String 传递给 通过使用 & 符号 (&) 获取 &str 的函数

    你不能用切片做的一件有用的事情是增加字符串的大小,在这种情况下你需要一个对字符串的可变引用。一个例子是read_line 函数,它将字符串数据附加到buf

    pub fn read_line(&self, buf: &mut String) -> Result<usize>

    【讨论】:

    • "大多数时候字符串切片更有用,因为你可以引用子字符串,这使它更灵活。" ??? string 也可以做到这一点,这实际上是您从字符串创建 str 的方式。
    猜你喜欢
    • 2017-01-12
    • 1970-01-01
    • 1970-01-01
    • 2021-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多