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

为什么第一个例子有效,而第二个却不行?

推荐答案

.clone()返回其接收器.&str上的clone()返回&str.如果你想要一个String,你需要一个不同的方法,在本例中是.to_owned().

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

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


到目前为止,两者都已编译,但在test_clone()c1String,在test_to_owned()&str.我很确定它可以编译,因为Rust现在对自动引用和取消引用值更加宽容.在这个特定的例子中,我相信c1 == s1行的编译方式就像&*c1 == s1行一样.如果你想证明所涉及的类型,你可以添加一个故意的类型错误,例如let _: i32 = c1;,错误消息将显示该类型.

Rust相关问答推荐

在Rust中创建可变片段的可变片段的最有效方法是什么?

阻止websocket中断的中断中断的终端(操作系统错误4)

空字符串转换为Box字符串时是否分配?<>

如何使用Match比较 struct 中的值

如何仅使用http机箱发送http请求?

使用模块中的所有模块,但不包括特定模块

Trait bound i8:来自u8的不满意

Rust编译器似乎被结果类型与anyhow混淆

对reqwest提供的这种嵌套JSON struct 进行反序列化

将 &str 或 String 保存在变量中

Option<&T> 如何实现复制

为什么 Rust 字符串没有短字符串优化 (SSO)?

go 重并堆积MPSC通道消息

Rust编译器通过哪些规则来确保锁被释放?

使用在功能标志后面导入的类型,即使未启用功能标志

第 7.4 章片段中如何定义 `thread_rng`

Rust HRTB 是相同的,但编译器说一种类型比另一种更通用

`if let` 只是另一种编写其他 `if` 语句的方式吗?

在 Rust 中组合特征的不同方法是否等效?

为什么我返回的 impl Trait 的生命周期限制在其输入的生命周期内?