Appearance
✍读书笔记:『Rusts程序设计语言』ch04 - 01
Rust 所有权
Rust 这个语言本身没有垃圾回收 GC,所以可以作为一门系统级编程语言,但是它同样也不需要进行对堆区内存的手动回收。Rust 有自己的一套机制,用于对内存的回收,这套机制叫做所有权(ownership)。
所有权的规则:
- Rust 的每一个值都有所有者(owner),即变量;
- 值在任一时刻只有一个所有者;
- 当所有者(变量)离开作用域,这个值被回收。
Rust 移动
打个比方:
rust
let a = 3;
let b = a;第一句代码声明了 3 的所有者是变量 a。然后将 a 赋值给 b,那么 3 的所有者同时也是 b?不对,因为 3 是在栈上的基础变量,所以第二句代码实际是复制了一份 3,这两个 3 其实是不同的值,它们有各自的拥有者。
再来看下堆中的值:
rust
let s1 = String::from("hello");
let s2 = s1;有一定其他语言编程经验的朋友看到这段代码的时候,马上会思考 rust 是使用深拷贝(复制值)还是浅拷贝(复制引用,指针)的问题。但如果按照所有权的规则 2,rust 只能是深拷贝,但这样对内存和CPU使用率来说显然不合实际。所以 rust 采取的方法是移动(move)。
通过移动,字符串值"hello"的拥有者从s1移动到了s2,此时如果读取s1的值,编译器会出错borrow of moved value: s1,意思是借用的值已经被转移了。
Rust 参数传递
有其他编程经验的朋友应该知道,函数的参数传递分为形式参数和实际参数,当函数调用的时候,实际参数会赋值给函数签名中的形式参数。因为上面说过,rust 复杂类型的赋值实际上是移动。
rust
let s = String::from("hello");
somefunc(s);
// s 已经没有值了一般的办法是返回处理后的数据用变量接收:
rust
let s1 = String::from("hello");
let s2 = reverse(s);如果s1确实不再被需要使用,上面的代码非常完美。然而,有些情况我们同时需要处理后的数据和处理前的数据。这个时候可以利用元组把原数据和处理的数据同时传出。但是,这样很!不!优!雅!!
rust
fn somefunc(s: String) -> (String, String) {}