Memory 将字符串转换为&;时,切片和显式重新箭头之间是否有区别;strs?

Memory 将字符串转换为&;时,切片和显式重新箭头之间是否有区别;strs?,memory,type-conversion,rust,Memory,Type Conversion,Rust,以下两个例子是否等效 例1: let x = String::new(); let y = &x[..]; 例2: let x = String::new(); let y = &*x; 一个比另一个更有效还是基本相同?对于String和Vec,它们是完全相同的 […]语法导致调用Index::Index(),而不仅仅是[0..collection.len()]的糖。后者将引入绑定检查的成本。令人高兴的是,这不是生锈的情况,所以它们都一样快 相关代码: (仅返回触发d

以下两个例子是否等效

例1:

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

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

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

对于
String
Vec
,它们是完全相同的

[…]
语法导致调用
Index::Index()
,而不仅仅是
[0..collection.len()]
的糖。后者将引入绑定检查的成本。令人高兴的是,这不是生锈的情况,所以它们都一样快


相关代码:

  • (仅返回触发deref强制的
    self
    ,从而执行与just
    deref
    完全相同的代码)
    • 在和的情况下,它们做相同的事情。然而,总的来说,它们并不完全相同

      首先,你必须理解。这种特性是在类型逻辑上“包装”某个较低级别、较简单的值的情况下实现的。例如,所有的“智能指针”类型(
      Box
      Rc
      Arc
      )都实现
      Deref
      )以允许您访问其内容

      它还用于
      String
      Vec
      String
      “derefs”到更简单的
      str
      Vec
      derefs到更简单的
      [T]

      编写
      *s
      只是手动调用,将
      s
      转换为其“更简单的形式”。但是,它几乎总是被编写成
      &*s
      ,尽管
      Deref::Deref
      签名表示它返回一个借用的指针(
      &Target
      ),编译器会插入第二个自动Deref。例如,
      {let x=Box::new(42i32);*x}
      导致的是
      i32
      ,而不是
      &i32

      所以
      &*s
      实际上只是
      Deref::Deref(&s)
      的简写

      s[…]
      是由trait实现的
      s.index(RangeFull)
      的语法糖。这意味着对被索引对象的“整个范围”进行切片;对于
      String
      Vec
      ,这将为您提供整个内容的一部分。同样,结果在技术上是一个借用的指针,但是Rust自动取消了这个指针的顺序,因此它也几乎总是被写入
      &s[…]

      那么有什么区别呢?保持这种想法;让我们来谈谈
      Deref
      链接

      举一个具体的例子,因为您可以将
      String
      视为
      str
      ,所以让
      str
      s上可用的所有方法在
      String
      s上自动可用将非常有帮助。Rust不是通过继承,而是通过
      Deref
      链接来实现这一点

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

      这意味着当您调用
      s.chars()
      其中
      s
      是一个
      String
      ,实际发生的情况是您正在调用
      s.deref().chars()
      ,因为
      String
      没有一个名为
      chars
      的方法,但是(向上滚动查看
      String
      仅获取此方法,因为它实现了
      Deref

      <>回到原来的问题,<>代码> *s>代码>和<>代码> & [s]…[/COD] >当<代码> S/<代码>不只是<代码> String < /C> >或<代码> VEC>代码>时,我们举几个例子:

      • s:String
        和*s:&str
        &s[…]:&str
      • s:&String
        和*s:&String
        &s[…]:&str
      • s:Box
        和*s:&String
        &s[…]:&str
      • s:Box
        和*s:&Rc
        和s[…]:&str
      &s
      只会剥离一层间接寻址。
      &s[…]
      会剥离所有层。这是因为没有一个
      Box
      Rc
      &code>等。实现
      索引
      特性,因此
      Deref
      链接会导致调用
      s.Index(RangeFull)
      链接所有这些中间层

      你应该使用哪一个?无论你想用哪一个。如果你想精确控制要剥离多少层间接寻址,请使用
      &*s
      (或
      &**s
      ,或
      &***s
      )如果你想剥离它们,只需获取值的最内层表示,请使用
      &s[…]

      或者,您可以像我一样使用
      &*s
      ,因为它从左到右读取,而
      &s[…]
      从左到右再从左读取,这让我很恼火。:)

      补遗
      • 这里有一个相关的概念
      • 还有和,它们完成了上述所有操作,但用于
        &mut
        而不是
        &

      如果答案合适,我还想将问题扩展到
      Vec
      &[T]