在Rust中,Clone
是指定clone
方法(和clone_from
)的特征。一些性状,如StrSlice
和CloneableVector
,指定了to_owned
fn。为什么一个实现需要这两者?有什么关系?
我用Rust字符串做了一个实验,它有两种方法,它证明了这是有区别的,但我不理解它:
fn main() {
test_clone();
test_to_owned();
}
// compiles and runs fine
fn test_clone() {
let s1: &'static str = "I am static";
let s2 = "I am boxed and owned".to_string();
let c1 = s1.clone();
let c2 = s2.clone();
println!("{:?}", c1);
println!("{:?}", c2);
println!("{:?}", c1 == s1); // prints true
println!("{:?}", c2 == s2); // prints true
}
fn test_to_owned() {
let s1: &'static str = "I am static";
let s2 = "I am boxed and owned".to_string();
let c1 = s1.to_owned();
let c2 = s2.to_owned();
println!("{:?}", c1);
println!("{:?}", c2);
println!("{:?}", c1 == s1); // compile-time error here (see below)
println!("{:?}", c2 == s2);
}
to_owned
示例的编译时错误为:
error: mismatched types: expected `~str` but found `&'static str`
(str storage differs: expected `~` but found `&'static `)
clone.rs:30 println!("{:?}", c1 == s1);
为什么第一个例子可以工作,而第二个不行?
发布于 2014-03-08 14:06:37
.clone()
返回它的接收器。&str
上的clone()
返回一个&str
。如果需要String
,则需要一个不同的方法,在本例中为.to_owned()
。
对于大多数类型,clone()
就足够了,因为它只在底层类型上定义,而不是在引用类型上定义。但是对于str
和[T]
,clone()
是在引用类型(&str
和&[T]
)上实现的,因此它的类型是错误的。它还在拥有的类型(String
和Vec<T>
)上实现,在这种情况下,clone()
将返回另一个拥有的值。
第一个示例之所以有效,是因为c1
和s1
(以及c2
和s2
)具有相同的类型。您的第二个示例失败了,因为它们不是这样(c1
是String
,而s1
是&str
)。这是一个很好的例子,说明了为什么分离的方法是必要的。
到目前为止,两者都可以编译,但在test_clone()
中,c1
是String
,在test_to_owned()
中是&str
。我非常确定它的编译方式是Rust现在在自动引用和取消引用值方面更加宽松。在这个特定的例子中,我相信c1 == s1
代码行被编译得就像&*c1 == s1
一样。如果您希望证明所涉及的类型,您可以添加一个故意的类型错误,例如let _: i32 = c1;
,错误消息将显示该类型。
https://stackoverflow.com/questions/22264502
复制相似问题