Rust 通过 借用(Borrowing)
在使用某个变量的指针或引用。
获取变量的引用,称之为 借用(borrowing) 。
引用与解引用
引用是为了解决在使用函数时,频繁地传递所有权。
引用只是获取了引用权,而不是获取所有权。
rust
fn main() {
let s = String::from("Hello");
let s1 = &s; // 不可变引用
let s2 = &mut 2; // 可变引用
/*
这个程序不能编译通过。
因为不能同时存在 可变引用 和 不可变引用。
*/
}
引用与变量一样,也是默认为不可变。
不仅是原来的变量是可变就可以,必须是引用也是可变的,即在使用let s1 = &mut s
或传递参数 &mut s
。
rust
fn main() {
let mut s = String::from("hello, ");
push_str(&mut s)
}
fn push_str(s: &mut String) {
s.push_str("world")
}
解引用
rust
fn main() {
let s = String::from("hello");
let s1 = &s; // s 的 不可变引用
println!("{}",*s1);
}
可以在一个引用作用域中存在多个不可变引用,但只能存在一个可变引用。
引用的作用域是从引用开始,到该引用的最后一次使用。
rust
fn main() {
let mut s = String::from("hello");
let r1 = &s;
let r2 = &s;
println!("{} and {}", r1, r2);
// 新编译器中,r1,r2作用域在这里结束
let r3 = &mut s;
println!("{}", r3);
} // 老编译器中,r1、r2、r3作用域在这里结束
// 新编译器中,r3作用域在这里结束
可变引用只能存在一个。直到该引用结束,才可以使用另一个。
在一个可变引用的引用作用域结束之间,无法创建第二个可变引用。
不能从一个不可变引用上借用可变。可以从可变对象上借用可变。
Rust 不允许出现 悬垂引用,即空的引用。悬垂引用会再编译时被检测出来 。
rust
fn main() {
let reference_to_nothing = dangle();
}
fn dangle() -> &String {
let s = String::from("hello");
&s
}
/*
编译不能通过,因为返回的引用指针是空的,
这种情况更推荐转移所有权。
**/
借用规则
- 同一时刻(在当前作用域中),只能拥有一个可变引用,或多个不可变引用。
- 引用必须总是有效的。
ref
ref
与 &
类似,可以用来获取一个值的引用。
rust
fn main() {
let c = '中';
let r1 = &c;
let ref r2 = c;
assert_eq!(*r1, *r2);
// 判断两个内存地址的字符串是否相等
assert_eq!(get_addr(r1),get_addr(r2));
}
// 获取传入引用的内存地址的字符串形式
fn get_addr(r: &char) -> String {
format!("{:p}", r)
}
ref
同样获取c的引用,而且指向了同一个内存地址。