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

问题描述 投票:27回答:1

在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);

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

rust
1个回答
30
投票

.clone()返回其接收器。在clone()上的&str返回&str。如果你想要一个String,你需要一个不同的方法,在这种情况下是.to_owned()

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

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


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

© www.soinside.com 2019 - 2024. All rights reserved.