memory - 将字符串转换为 &strs 时,切片和显式重新借用之间有区别吗?

标签 memory type-conversion rust

下面两个例子等价吗?

示例 1:

let x = String::new();
let y = &x[..];

示例 2:
let x = String::new();
let y = &*x;

一个比另一个更有效还是它们基本相同?

最佳答案

String 的情况下和 Vec ,他们做同样的事情。然而,总的来说,它们并不完全相同。

首先你要了解 Deref .在类型逻辑上“包装”一些较低级别的更简单值的情况下,会实现此特征。例如,所有“智能指针”类型( BoxRcArc )都实现了 Deref让您可以访问其内容。

它也适用于 StringVec :String “解引用”到更简单的 str , Vec<T>取消引用更简单的 [T] .

写作 *s只是手动调用 Deref::deref s变成“更简单的形式”。几乎总是写成 &*s ,然而:虽然 Deref::deref签名说它返回一个借用的指针( &Target ),编译器插入第二个自动解引用。这是这样的,例如,{ let x = Box::new(42i32); *x }结果是 i32而不是 &i32 .

所以&*s真的只是 Deref::deref(&s) 的简写.
s[..]s.index(RangeFull) 的语法糖,由 Index 实现特征。这意味着对被索引事物的“整个范围”进行切片;对于两者 StringVec ,这为您提供了整个内容的一部分。同样,结果在技术上是一个借用的指针,但 Rust 也会自动解引用这个指针,所以它也几乎总是写成 &s[..] .

那么有什么区别呢?保持这个想法;咱们聊聊Deref链接。

举个具体的例子,因为你可以查看一个String作为 str ,在 str 上提供所有方法会非常有帮助。 s 在 String 上自动可用s 也是。 Rust 通过 Deref 做到这一点,而不是继承。链接。

它的工作方式是,当您要求对某个值使用特定方法时,Rust 首先查看为该特定类型定义的方法。假设它没有找到您要求的方法;在放弃之前,Rust 会检查 Deref执行。如果它找到一个,它会调用它,然后再试一次。

这意味着当您调用 s.chars() 时哪里sString ,实际发生的情况是您正在调用 s.deref().chars() , 因为 String没有名为 chars 的方法,但是 str does (向上滚动可以看到 String 只得到这个方法,因为它实现了 Deref<Target=str> )。

回到最初的问题,&*s 之间的区别和 &s[..]s 时会发生什么不仅仅是StringVec<T> .让我们举几个例子:

  • s: String ; &*s: &str , &s[..]: &str .
  • s: &String :&*s: &String , &s[..]: &str .
  • s: Box<String> :&*s: &String , &s[..]: &str .
  • s: Box<Rc<&String>> :&*s: &Rc<&String> , &s[..]: &str .
  • &*s只剥离一层间接。 &s[..]剥掉所有这些。这是因为 Box 都没有, Rc , &等实现 Index特质,所以 Deref链接导致调用 s.index(RangeFull)链接所有这些中间层。

    你应该使用哪一个?随心所欲。使用 &*s (或 &**s ,或 &***s )如果您想精确控制要剥离的间接层数。使用 &s[..]如果您想将它们全部剥离并获得值的最内层表示。

    或者,您可以按照我的操作使用 &*s因为它从左到右读取,而 &s[..]再次从左到右到左阅读,这让我很恼火。 :)

    附录
  • Deref coercions的相关概念.
  • 还有 DerefMut IndexMut 可以完成上述所有操作,但对于 &mut而不是 & .
  • 关于memory - 将字符串转换为 &strs 时,切片和显式重新借用之间有区别吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33860750/

    相关文章:

    java - 为什么 Byte.parseByte 的结果被识别为整数?

    go - 从 yaml 文件中删除属性

    c++ - char 到 int 的转换 - 这里发生了什么?

    json - 无法解析 `Responder<' _, '_>` 未针对 `rocket_contrib::json::Json<MyStruct>` 实现

    lambda - 传递和评估防 rust 封闭

    java - 使用 Xmx 增加 JVM 堆内存不起作用

    iphone - xCode 4 中的内存监视器 - iPhone

    C: 动态 2D 矩阵重新分配

    matrix - 是否可以编写一个可以转置矩阵的rust宏?

    r - 覆盖 R 对象时如何管理内存?