引用以及移动与复制

Car*_*cho 4 ownership rust

我正在阅读《Rust》一书的第 4 章,我有 Python 背景。

让我有点困惑的是这不能编译:

fn do_something(s3: String) {
    println!("{}", s3);
}

fn main() {
    let s = String::from("Hello");
    do_something(s);
    println!("{}", s);
}
Run Code Online (Sandbox Code Playgroud)

(因为它不应该,因为 s 在函数调用中被移动),但是这样做:

fn do_something(s3: &String) {
    println!("{}", s3);
}

fn main() {
    let s1 = String::from("Hello");
    let s2 = &s1;
    do_something(s2);
    println!("{}", s2);
}
Run Code Online (Sandbox Code Playgroud)

如果我理解正确的话,这是因为 s1 已经是一个指针,所以 s2 是一个指向(堆栈分配的)指针的指针(好吧,是一个引用)。因此,s2在函数调用中被复制而不是被移动。是这样吗?上面的和这个一样吗?

fn main() {
    let a = 5;
    let b = &a;
    do_something(b);
    println!("{}", b);
}
Run Code Online (Sandbox Code Playgroud)

Joh*_*ica 5

fn main() {
    let s1 = String::from("Hello");
    let s2 = &s1;
    do_something(s2);
    println!("{}", s2);
}
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为引用是Copy. s2被复制,不被移动,并且可以在调用后继续使用do_something


上面的和这个一样吗?

fn main() {
    let a = 5;
    let b = &a;
    do_something(b);
    println!("{}", b);
}
Run Code Online (Sandbox Code Playgroud)

是的。a是否或s1是并不重要Copy,重要的是bs2是。


我想我的问题是,它们是Copy因为它们总是指向堆栈分配数据的指针吗?

所有共享引用都是Copy因为总体实现:

impl<'_, T> Copy for &'_ T
where
    T: ?Sized, 
Run Code Online (Sandbox Code Playgroud)

.data引用指向何处、堆栈、堆、节或其他任何地方并不重要。引用是字大小的小值,复制它们既方便又高效,因此 Rust 使它们成为Copy

这是通常的衡量标准:复制有效吗?Strings 不是,Copy因为克隆它们是一个昂贵的O ( n ) 操作。&strs 作为引用, Copy因为复制指针很便宜。

(当然,这不是唯一的度量标准。某些类型不是唯一的度量Copy标准,因为它们在逻辑上是唯一的。例如,Box也只是一个指针,但它是一个拥有的类型,而不是共享引用。)