Rust 引用和借用


Rust 2018 Edition 使用 "Non-lexical lifetimes"(NLL),之前版本的 Rust 采用的是 Lexical Lifetimes 策略,即变量和借用的生命周期从声明开始,到所在语句块结束。
// RAII:一种编程技术,在其构造时获取资源,在对象生命期控制对资源的访问使之始终保持有效,最后在对象析构(丢弃)的时候释放资源。
// std::io::stdin().lock().lines(); 不能连起来些,临时 RAII 值在借用时已经被释放
// NLL 是一种检查机制,实际释放还是在离开作用域时

所有权规则:
  1. Rust 中的每一个值都有一个被称为其 所有者(owner)的变量。
  2. 值有且只有一个所有者。
  3. 当所有者(变量)离开作用域,这个值将被丢弃。// 注意 NLL
Rust 永远也不会自动创建数据的 "深拷贝"。因此,任何 自动 的复制可以被认为对运行时性能影响较小。

当所有权转移时,数据的可变性可能发生改变。

获取引用作为函数参数称为借用borrowing

规则一:在特定作用域中的特定数据有且只有一个可变引用
// 这个限制的好处是 Rust 可以在编译时就避免数据竞争。数据竞争data race)类似于竞态条件,它可由这三个行为造成:
  • 两个或更多指针同时访问同一数据。
  • 至少有一个指针被用来写入数据。
  • 没有同步数据访问的机制。
// 可以使用大括号来创建一个新的作用域(确保使用另一个可变引用时前一个释放,NLL 后不需要使用此方法),以允许拥有多个可变引用,只是不能 同时 拥有

规则二:不能在拥有不可变引用的同时拥有可变引用
// 不可变引用的用户可不希望在他们的眼皮底下值就被意外的改变了!
注意一个引用的作用域从声明的地方开始一直持续到最后一次使用为止,所以在使用完不可变引用再使用可变引用是允许的

在具有指针的语言中,很容易通过释放内存(如离开作用域)时保留指向它的指针而错误地生成一个 悬垂指针dangling pointer),Rust 编译器确保数据不会在其引用之前离开作用域 // 如果一个函数中离开作用域时清理一个数据,这时返回这个数据的引用时编译器会报错