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