字符串是丢弃还是复制?

8
我正在学习Rust的所有权。我的测试表明,在变量分配时,字符串字面值会被复制,而String实例会被移动。这是否意味着StringDrop类型,而字符串字面值是Copy类型? < p >variable_assign_test.rs

// variable assign test,

// assign variable on stack to another,
fn test_stack_assign() {
    let x = 5;
    let y = x; // data duplicated on stack,
    println!("x = {}, y = {}", x, y); // it's ok,
}

// assign variable on heap to another,
fn test_heap_assign() {
    let s1 = String::from("hello");
    let s2 = s1;    // now s1 is invalid, should not use it any more,
    // println!("{}", s1); // this won't compile,
    println!("s2 = {}", s2); // it's ok,
}

fn test_tuple_assign() {
    let pa = (1, 2);
    let pb = pa;
    println!("pa = {:?}, pb = {:?}", pa, pb); // it's ok,

    // tuple that contains string literal,
    let name_monica = "monica";
    let monica = (11, name_monica);
    let monica2 = monica;
    println!("monica = {:?}, monica2 = {:?}", monica, monica2);

    // tuple that contains String instance,
    let name_eric = String::from("eric");
    let eric = (12, name_eric);
    let eric2 = eric; // eric is invalid now,
    // println!("eric = {:?}, eric = {:?}", eric, eric2); // this won't compile,
}

fn main() {
    test_stack_assign();
    test_heap_assign();
    test_tuple_assign();
}

使用rustc variable_assign_test.rs -o a.out编译,然后用./a.out运行。

如果取消注释test_tuple_assign()的最后一行,会出现value used here after move的错误,原因是变量eric已经被移动。


谢谢,我认为你的问题更容易理解了 :) - Boiethios
1个回答

14

是的

明确一下,所有不可变引用(&T)都是Copy,而可变引用(&mut T)则是移动的。 &'static str,即字符串字面值的类型,只是&T的一种特殊情况,是一个不可变引用,因此是Copy

另一方面,String实例是其内容动态分配缓冲区的唯一所有者。这防止了它被Copy(单所有者)并要求实现Drop(以释放动态分配的缓冲区)。

具体来说,String并没有直接实现Drop,而是一个围绕着Vec<u8>的包装器,后者本身实现了Drop。行为是相同的,只是StringDrop实现是自动生成的,而Vec<u8>的实现是手动编写的


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接