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不是继承,而是通过链接实现这一点.strStringDeref
它的工作方式是,当您在值上请求特定方法时,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 的 Stringderef 的 StringindexofVec(只返回self触发deref强制因此执行完全相同的代码deref)deref 的 Vec| 归档时间: |
|
| 查看次数: |
172 次 |
| 最近记录: |