1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
// 所有权规则
// 1. Rust 中每一个值都有一个被称为其 `所有者(owner)`的变量
// 2. 值有且只有一个所有者
// 3. 当所有者(变量)离开作用域时,这个值将被丢弃
//
fn main() {
// String 类型分配到堆上
let mut s1 = String::from("hello");
println!("{}", s1);
s1.push_str(", world!");
println!("{}", s1);
let s2 = s1.clone();
println!("s1 = {}, s2 = {}, (s1 == s2) = {}", s1, s2, s1.eq(&s2));
// 将值传递给函数在语义上与变量赋值相似。向函数传递值可能会移动或者复制,就像赋值语句一样。
let s3 = String::from("hello"); // s3 进入作用域
takes_ownership(s3); // s3 的值移动到函数里
// s3 在这里不再有效
// Rust 有一个叫做 `Copy` trait 的特殊注解,可以用在类似整形这样的存储在栈上的类型上。
// 如果一个类型拥有 `Copy` trait,一个旧的变量在将其赋值给其他变量后仍然可用。
// Rust 不允许自身或其他任何部分实现了 `Drop` trait 的类型使用 `Copy` trait。
// 如果我们对其值离开作用域时需要特殊处理的类型使用 `Copy` 注解,将出现一个编译时错误。
// 任何简单标量值的组合可以是 `Copy` 的,不需要分配内存或某种形式资源的类型是`Copy`的。
//
// - 所有整形类型,如: u32
// - 布尔类型, bool
// - 所有浮点数类型,如:f64
// - 字符类型,char
// - 元祖,当且仅当其包含类型也是 `Copy` 的时候。比如, (i32, i32) 是 `Copy` 的, 但 (i32, String) 不是
let x = 5; // x 进入作用域
makes_copy(x); // x 应该移动函数里
println!("copied i32: {}", x); // 但 i32 是 Copy 的,所以在后面继续使用x
// 返回值也可以转移所有权
let s4 = gives_ownership();
println!("函数返回值获取所有权: {}", s4);
let s5 = String::from("hello");
let s6 = takes_and_gives_back(s5); // s4 被移动到 takes_and_gives_back 中, 它也将返回值移给 s5
println!("takes and gives back: {}", s6);
} // 这里, s6 移出作用域并被丢弃. s5 也移出作用域, 但已被移走, 所以什么也不会发生. s4 移出作用域并被丢弃.
fn takes_ownership(some: String) { // some 进入作用域
println!("in function takes_ownership: {}", some);
} // 这里, some 移出作用域并调用 `drop` 方法。占用的内存被释放。
fn makes_copy(some_integer: i32) { // some 进入作用域
println!("{}", some_integer);
} // 这里,some_integer 移出作用域。不会有特殊操作。
fn gives_ownership() -> String {
let some_string = String::from("hello"); // some_string 进入作用域
some_string // 返回 some_string 并移除给调用的函数
}
fn takes_and_gives_back(a_string: String) -> String { // a_string 进入作用域
a_string // 返回 a_string 并移出给调用函数
}