RUST——所有权

发布时间 2023-04-12 10:01:14作者: 理想国的糕

1 所有权

Link

1.1 概念

fn main() {
    {
        let s="hello";
    }
    println!("{s}");//错误
}
~  
  • s进入作用域时,有效
  • 持续到离开作用域为止
    如果运行上面的代码片段,会发现会报错,因为s只在{}对应的作用域有效,出来即删

1.2 拷贝

1.2.1 浅拷贝


下面的这段代码是错误的,因为s1拷贝给s2后,自动失效

fn main() {
    let s1 = String::from("hello");
    let s2 = s1;

    println!("{}, world!", s1);//s1已经失效了
}

报错信息:

$ cargo run
   Compiling ownership v0.1.0 (file:///projects/ownership)
error[E0382]: borrow of moved value: `s1`
 --> src/main.rs:5:28
  |
2 |     let s1 = String::from("hello");
  |         -- move occurs because `s1` has type `String`, which does not implement the `Copy` trait
3 |     let s2 = s1;
  |              -- value moved here
4 |
5 |     println!("{}, world!", s1);
  |                            ^^ value borrowed here after move
  |
  = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)

For more information about this error, try `rustc --explain E0382`.
error: could not compile `ownership` due to previous error

如果想进行深拷贝,则需要使用clone方法:

fn main() {
    let s1 = String::from("hello");
    let s2 = s1.clone();
    println!("s1 = {}, s2 = {}", s1, s2);
}

1.2.2 深拷贝

但是下面的代码可以正常运行,因为整型变量是存放在上的,是属于深度拷贝

fn main() {
    let x = 5;
    let y = x;

    println!("x = {}, y = {}", x, y);
}

1.2.3 返回值和作用域

比如下面这段代码

fn main() {
    let s=String::from("hello");
    takes_ownership(s);
    //println!("after:{s}");
    let x=5;
    makes_copy(x);
    println!("after:{x}");
}
fn takes_ownership(some_string: String) { // some_string 进入作用域
    println!("{}", some_string);
}
fn makes_copy(some_integer: i32) { // some_integer 进入作用域
    println!("{}", some_integer);
}

第一个被注释掉的println!()是无法编译的,因为s在被函数调用后,在函数中存在有效,出来之后的作用域失活

转移返回值的所有权
一个例子,同时熟悉一下rust语言的函数可以返回元组作为返回值

fn main() {
    let s1 = String::from("hello");

    let (s2, len) = calculate_length(s1);

    println!("The length of '{}' is {}.", s2, len);
}

fn calculate_length(s: String) -> (String, usize) {
    let length = s.len(); // len() 返回字符串的长度

    (s, length)
}