cha*_*had 11 memory type-conversion rust
以下两个例子是等效的吗?
例1:
let x = String::new();
let y = &x[..];
Run Code Online (Sandbox Code Playgroud)
例2:
let x = String::new();
let y = &*x;
Run Code Online (Sandbox Code Playgroud)
一个比另一个更有效还是基本相同?
DK.*_*DK. 10
在的情况下,String
与Vec
他们做同样的事情.但总的来说,它们并不完全相同.
首先,你必须明白Deref
.这种特性是在类型在逻辑上"包装"某些较低级别,更简单的值的情况下实现的.例如,所有的"智能指针"类型的(Box
,Rc
,Arc
)执行Deref
给你访问他们的内容.
它也实现了String
和Vec
:String
"derefs"更简单str
,Vec<T>
derefs更简单[T]
.
编写*s
只是手动调用Deref::deref
以变成s
"更简单的形式".&*s
然而,它几乎总是被写入:虽然Deref::deref
签名表示它返回一个借来的指针(&Target
),但编译器会插入第二个自动deref.例如,这{ let x = Box::new(42i32); *x }
导致i32
而不是a &i32
.
所以&*s
真的只是简写Deref::deref(&s)
.
s[..]
是特征糖s.index(RangeFull)
,由Index
特质实现.这意味着要对被索引事物的"整个范围"进行分割; 两个String
和Vec
,这给你的全部内容的片段.再次,结果是技术上借来的指针,但防锈自动derefs这一个,以及,所以它也几乎总是写&s[..]
.
那有什么区别?坚持这个想法; 我们来谈谈Deref
链接.
举一个具体的例子,因为你可以将a String
视为a str
,所以在s上自动提供所有可用的方法也是非常有帮助的.Rust不是继承,而是通过链接实现这一点.str
String
Deref
它的工作方式是,当您在值上请求特定方法时,Rust首先查看为该特定类型定义的方法.假设它没有找到你要求的方法; 在放弃之前,Rust将检查Deref
实施情况.如果找到一个,它会调用它然后再次尝试.
这意味着,当你调用s.chars()
其中s
的一个String
,什么是真正发生的事情是,你打电话s.deref().chars()
,因为String
不具有一个调用的方法chars
,但str
不(滚动地看到,String
只得到这种方法,因为它实现Deref<Target=str>
).
再回到原来的问题,之间的区别&*s
,并&s[..]
在发生什么的时候s
不只是 String
或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
只有不断剥离掉一个间接的层. &s[..]
把所有这些都剥掉了.这是因为没有Box
,Rc
,&
,等等实现Index
的性状,所以Deref
链接原因调用s.index(RangeFull)
通过所有这些中间层以链.
你应该使用哪一个?无论你想要什么.如果要准确控制要剥离的间接层数,请使用&*s
(或&**s
,或&***s
).使用如果要剥夺他们全部关闭,并刚刚获得的价值的最里面的表示.&s[..]
或者,你可以做我做的和使用,&*s
因为它从左到右&s[..]
阅读,而从左到右再次读取,这让我很烦.:)
他们是完全为同String
和Vec
.
该[..]
语法结果在一个呼叫Index<RangeFull>::index()
,它不只是糖[0..collection.len()]
.后者会引入绑定检查的成本.很高兴Rust的情况并非如此,所以他们都同样快.
相关代码:
index
的 String
deref
的 String
index
ofVec
(只返回self
触发deref强制因此执行完全相同的代码deref
)deref
的 Vec
归档时间: |
|
查看次数: |
172 次 |
最近记录: |