Rust“所有权”思想

 

 

 

 

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

}

 

does not implement the `Copy` trait
cargo build
   Compiling own v0.1.0 (/data2/rust/clone4)
error[E0382]: borrow of moved value: `s1`
 --> src/main.rs:4:24
  |
2 |         let s1 = String::from("hello"); 
  |             -- move occurs because `s1` has type `std::string::String`, which does not implement the `Copy` trait
3 |         let s2 = s1; 
  |                  -- value moved here
4 |          println!("s1 : {}", s1);
  |                              ^^ value borrowed here after move

error: aborting due to previous error

For more information about this error, try `rustc --explain E0382`.
error: could not compile `own`.

To learn more, run the command again with --verbose.

 

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

}

 

cargo build
   Compiling own v0.1.0 (/data2/rust/clone4)
    Finished dev [unoptimized + debuginfo] target(s) in 0.50s
[root@bogon clone4]# cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.01s
     Running `target/debug/own`
s2 : hello
s3 : hello

 

 

1、Rust使用所有权系统(ownership)管理内存,不同于Ruby的GC和C语言的亲自分配和释放。原理是编译器编译时根据一系列规则检查,从而保证运行时的安全和效率。(我理解为对代码的预处理,检查栈和堆使用的合理性)

2、栈(Stack)和堆(Heap)是代码在运行时可供使用的内存。使用栈内存大小固定且效率高。反之,堆内存大小动态且效率相对较低。因为堆内存是动态所以需要指针访问,从而保证动态分配内存,而Rust的所有权就是管理堆数据。

3、Rust中任一变量在任一时刻有且只有一个所有者(owner)。当所有者离开作用域(表现在代码中的“”后会自动执行 drop 释放当前作用域内存),这个值将被丢弃。例如:

{
                     // s 无效
    let s = "hello"; // s 进入作用域,有效。此时hello字符串是硬编码进程序的,不可改变。
}                    // s 离开作用域,无效。此时自动调用 drop 函数 (源于 C++ 的 RAII)

4、动态长度的字符串String数据分配在堆上。例如:

let mut s = String::from("hello");
s.push_str(" world");
println!("{}", s);

5、堆上的数据占用内存大,所以有 移交 和 克隆 的区别。例如:

let s1 = String::from("hello"); // 此时在堆上初始化hello字符串,所有者是s1
let s2 = s1;                    // 此时堆上的hello字符串,所有者从s1移交给了s2
                                // 根据“任一时刻有且只有一个所有者”,s1不存在了
let s3 = s2.clone();            // 此时在堆上初始化第二个hello字符串,所有者是s3

6、栈上的数据占用内存小,所以都是 克隆。例如:

let x = 5;
let y = x;                      // 此时栈上有两个5,所有者分别是 x和 y

7、将值传递给函数,等价于将值所有者移交给函数参数变量的所有者,函数结束将释放。例如:

fn main() {
    let s1 = gives_ownership();
    let s2 = String::from("hello");
    let s3 = takes_and_gives_back(s2);
} 
  // 此时执行drop释放堆中两个 hello 字符串,所有者是:s1 和 s3
  // hello -> s1
  // hello -> s2 -> a_string -> s3
fn gives_ownership() {
    let some_string = String::from("hello");
    some_string
}
fn take_and_gives_back(a_string: String) -> String {
    a_string
}

 cat src/main.rs 
fn main() {
    let s1 = gives_ownership();
        println!("s1 : {}", s1);
    //let s2 = String::from("hello");
    //let s3 = takes_and_gives_back(s2);
} 
  // 此时执行drop释放堆中两个 hello 字符串,所有者是:s1 和 s3
  // hello -> s1
  // hello -> s2 -> a_string -> s3
fn gives_ownership() {
    let some_string = String::from("hello");
    some_string
}
fn take_and_gives_back(a_string: String) -> String {
    a_string
}

 

cargo build
   Compiling own v0.1.0 (/data2/rust/ownship)
error[E0277]: `()` doesn't implement `std::fmt::Display`
 --> src/main.rs:3:22
  |
3 |     println!("s1 : {}", s1);
  |                         ^^ `()` cannot be formatted with the default formatter
  |
  = help: the trait `std::fmt::Display` is not implemented for `()`
  = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
  = note: required by `std::fmt::Display::fmt`
  = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0308]: mismatched types
  --> src/main.rs:12:5
   |
10 | fn gives_ownership() {
   |                      - help: try adding a return type: `-> std::string::String`
11 |     let some_string = String::from("hello");
12 |     some_string
   |     ^^^^^^^^^^^ expected `()`, found struct `std::string::String`

error: aborting due to 2 previous errors

Some errors have detailed explanations: E0277, E0308.
For more information about an error, try `rustc --explain E0277`.

 

 

8、由上可见,函数使用完一个变量后,值就被回收清理了。如果函数后继续使用,就需要传进去再反回来。例如:

fn main() {
    let s1 = String::from("hello");
    let (s2, len) = calculate(s1);
    println!("The length of '{}' is {}.", s2, len);
}
fn calculate_length(s: String) -> (String, usize) {
    let length = s.len();
    (s, length)
}

cat src/main.rs 
fn main() {
    //let s1 = gives_ownership();
        //println!("s1 : {}", s1);
    let s2 = String::from("hello");
    let s3 = take_and_gives_back(s2);
        println!("s3 : {}", s3);
} 
  // 此时执行drop释放堆中两个 hello 字符串,所有者是:s1 和 s3
  // hello -> s1
  // hello -> s2 -> a_string -> s3
//fn gives_ownership() {
//    let some_string = String::from("hello");
//    some_string
//}
fn take_and_gives_back(a_string: String) -> String {
    a_string
}
[root@bogon ownship]# cargo build
   Compiling own v0.1.0 (/data2/rust/ownship)
    Finished dev [unoptimized + debuginfo] target(s) in 0.41s
[root@bogon ownship]# cargo run
    Finished dev [unoptimized + debuginfo] target(s) in 0.01s
     Running `target/debug/own`
s3 : hello

 

 

 

 

posted on 2020-12-28 11:35  tycoon3  阅读(322)  评论(0编辑  收藏  举报

导航