在Rust中,clone()和to_owned()之间有什么区别?

时间:2014-03-08 03:09:52

标签: rust

在Rust中,Clone是一个指定clone方法(和clone_from)的特征。某些特征(如StrSliceCloneableVector)指定了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);

为什么第一个例子有效而不是第二个?

1 个答案:

答案 0 :(得分:29)

.clone()返回其接收者。 clone()上的&str会返回&str。如果您需要String,则需要使用其他方法,在本例中为.to_owned()

对于大多数类型,clone()就足够了,因为它只在基础类型上定义,而不在引用类型上定义。但对于str[T]clone()是在引用类型(&str&[T])上实现的,因此它的类型错误。它也在所拥有的类型(StringVec<T>)上实现,在这种情况下,clone()将返回另一个拥有的值。

您的第一个示例有效,因为c1s1(以及c2s2)具有相同的类型。您的第二个示例失败,因为它们没有(c1String,而s1&str)。这是为什么需要单独的方法的完美例子。


截至当前的Rust,现在都编译,但在test_clone() c1中是String而在test_to_owned()中它是&str。我很确定它会编译,因为Rust现在对自动引用和取消引用值更加宽容。在这个特定的例子中,我相信c1 == s1行的编译就像它说&*c1 == s1一样。如果您希望证明所涉及的类型,您可以添加故意类型错误,例如let _: i32 = c1;,错误消息将显示类型。