fn main() {
let s1 = String::from("hello");
let len = calculate_length(&s1);
println!("The length of '{}' is {}.", s1, len);
}
fn calculate_length(s: &String) -> usize { // s is a reference to a String
s.len()
} // 这里,s 离开了作用域。但因为它并不拥有引用值的所有权,
// 所以什么也不会发生
需求:我们必须将 String 返回给调用函数,以便在调用 calculatelength 后仍能使用 String,因为 String 被移动到了 calculate_length 内。
引用(_reference)像一个指针,因为它是一个地址,我们可以由此访问储存于该地址的属于其他变量的数据。与指针不同,引用确保指向某个特定类型的有效值。
借用(borrowing)是创建一个引用的行为。只能用,不能改。
可变引用
fn main() {
let mut s = String::from("hello");
change(&mut s);
}
fn change(some_string: &mut String) {
some_string.push_str(", world");
}
可变引用(mutable reference)允许我们修改一个借用的值。可变引用有一个很大的限制:在同一时间只能有一个对某一特定数据的可变引用。这些尝试创建两个 s 的可变引用的代码会失败:
let mut s = String::from("hello");
let r1 = &mut s;
let r2 = &mut s;
println!("{}, {}", r1, r2);
第一个可变的借入在 r1 中,并且必须持续到在 println! 中使用它,但是在那个可变引用的创建和它的使用之间,我们又尝试在 r2 中创建另一个可变引用,该引用借用与 r1 相同的数据。
这个限制的好处是 Rust 可以在编译时就避免数据竞争。数据竞争(data race)类似于竞态条件,它可由这三个行为造成:
- 两个或更多指针同时访问同一数据。
- 至少有一个指针被用来写入数据。
- 没有同步数据访问的机制。 ```rust let mut s = String::from(“hello”);
let r1 = &s; // 没问题 let r2 = &s; // 没问题 let r3 = &mut s; // 大问题
println!(“{}, {}, and {}”, r1, r2, r3);
我们也不能在拥有不可变引用的同时拥有可变引用。
<a name="WekQl"></a>
## 悬垂引用
在具有指针的语言中,很容易通过释放内存时保留指向它的指针而错误地生成一个 **悬垂指针**(dangling pointer),所谓悬垂指针是其指向的内存可能已经被分配给其它持有者。
```rust
fn main() {
let reference_to_nothing = dangle();
}
fn dangle() -> &String { // dangle 返回一个字符串的引用
let s = String::from("hello"); // s 是一个新字符串
&s // 返回字符串 s 的引用
} // 这里 s 离开作用域并被丢弃。其内存被释放。
// 危险!
$ cargo run
Compiling ownership v0.1.0 (file:///projects/ownership)
error[E0106]: missing lifetime specifier
--> src/main.rs:5:16
|
5 | fn dangle() -> &String {
| ^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
help: consider using the `'static` lifetime
|
5 | fn dangle() -> &'static String {
| ~~~~~~~~
For more information about this error, try `rustc --explain E0106`.
error: could not compile `ownership` due to previous error
引用的规则
- 在任意给定时间,要么 只能有一个可变引用,要么 只能有多个不可变引用。
- 引用必须总是有效的。