如果是String and Vec,他们做同样的事情。在general但是,它们并不完全等同。
首先你要明白Deref。当类型在逻辑上“包装”一些较低级别、更简单的值时,会实现此特征。例如,所有“智能指针”类型(Box
, Rc
, Arc
) 实施Deref
让您访问其内容。
它也被实施用于String
and Vec
: String
“derefs”更简单str
, Vec<T>
取消引用更简单的[T]
.
Writing *s
只是手动调用Deref::deref转动s
进入其“更简单的形式”。几乎总是这样写&*s
,但是:虽然Deref::deref
签名表示它返回一个借用的指针(&Target
),编译器插入第二个自动解引用。这是为了,例如,{ let x = Box::new(42i32); *x }
结果是i32
而不是一个&i32
.
So &*s
实际上只是简写Deref::deref(&s)
.
s[..]
是语法糖s.index(RangeFull)
,由Index特征。这意味着对被索引的事物的“整个范围”进行切片;对彼此而言String
and Vec
,这将为您提供整个内容的一部分。再次,结果是技术上一个借用的指针,但 Rust 自动取消引用这个指针as well,所以它也几乎总是写成&s[..]
.
那么有什么区别呢?保持这个想法;让我们来谈谈Deref
链接。
举个具体的例子,因为你可以查看String
as a str
, 这将是really有助于获得所有可用的方法str
s 自动可用String
也是如此。 Rust 不是继承,而是通过Deref
链接。
它的工作方式是,当您请求某个值的特定方法时,Rust 首先查看为该特定类型定义的方法。假设它没有找到您要求的方法;在放弃之前,Rust 会检查Deref
执行。如果它找到一个,它会调用它,然后再试一次.
这意味着当你打电话时s.chars()
where s
is a String
, 什么是actually正在发生的是你正在打电话s.deref().chars()
, 因为String
不have一个方法叫做chars
, but str does(向上滚动可以看到String
只得到这个方法,因为它实现了Deref<Target=str>
).
回到最初的问题,两者的区别&*s
and &s[..]
是在发生什么时s
is not just String
or Vec<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
only ever剥落one间接层。&s[..]
剥落他们全部。这是因为没有一个Box
, Rc
, &
, etc.实施Index
特质,所以Deref
链接导致调用s.index(RangeFull)
链接所有这些中间层。
您应该使用哪一个?无论你想要哪个。使用&*s
(or &**s
, or &***s
)如果你想控制exactly您想要剥离多少间接层。使用&s[..]
如果您想将它们全部剥离并仅获取该值的最内部表示形式。
或者,你可以做我所做的并使用&*s
因为它是从左到右读取的,而&s[..]
再次从左到右到左阅读,这让我很恼火。 :)
Addendum
- 有一个相关的概念Deref强制.
- 还有DerefMut and IndexMut执行上述所有操作,但是对于
&mut
代替&
.