Rust 中 *、&、mut、&mut、ref、ref mut 的用法和区别
在 Rust
中,*
、ref
、mut
、&
和 ref mut
是用于处理引用、解引用和可变性的关键字和操作符,它们在不同的上下文中有不同的用法。
一、*
解引用
*
属于操作符
1. 作用
用于解引用指针或引用,以访问其指向的值。
通过解引用,可以从指针或引用中获取实际的值。
2. 用法
2.1. 解引用不可变引用
fn main() {
let x = 5;
let y = &x; // y 是对 x 的不可变引用
println!("y: {}", *y); // 通过解引用 y 获取 x 的值,输出: y: 5
}
2.2. 解引用可变引用
fn main() {
let mut x = 10;
let y = &mut x; // y 是对 x 的可变引用
*y += 5; // 通过解引用 y 修改 x 的值
println!("x: {}", x); // 输出: x: 15
}
2.3. 解引用指针
fn main() {
let x = 42;
let y = &x as *const i32; // 创建不可变裸指针
unsafe {
println!("y: {}", *y); // 解引用不可变裸指针
}
let x = Box::new(10); // Box 智能指针
println!("x: {}", *x); // 解引用 Box,获取其值,输出: x: 10
}
二、&
借用引用
&
也是操作符
1. 作用
创建一个值的不可变引用,允许读而不获取所有权,该值在引用期间是只读的。
2. 用法
2.1. 不可变引用
fn main() {
let x = 10;
let y = &x; // y 是对 x 的不可变引用
println!("y: {}", y); // 输出: y: 10
}
2.2. 函数中的借用
fn print_value(x: &i32) {
println!("Value: {}", x);
}
fn main() {
let a = 10;
print_value(&a); // 传递 a 的不可变引用
}
2.3. match 中使用
fn main() {
let reference = &4;
match reference {
&val => println!("Got a value via destructuring: {:?}", val),
}
}
2.4. 结构体中使用
struct Point<'a> {
x: &'a i32,
y: &'a i32,
}
fn main() {
let x = 10;
let y = 20;
let point = Point { x: &x, y: &y }; // 使用引用初始化结构体字段
println!("Point: ({}, {})", point.x, point.y); // 输出: Point: (10, 20)
}
2.5. 集合中使用
fn main() {
let vec = vec![1, 2, 3];
for val in &vec {
println!("Value: {}", val); // 输出: 1, 2, 3
}
}
2.6. 切片中使用
fn main() {
let s = String::from("hello");
let slice = &s[0..2]; // 创建字符串切片
println!("Slice: {}", slice); // 输出: Slice: he
}
三、mut
可变
mut
是一个关键字
1. 作用
声明一个变量或引用为可变的,可以修改其值。
2. 用法
2.1. 可变变量
fn main() {
let mut x = 5; // x 是可变的
x += 1;
println!("x: {}", x); // 输出: x: 6
}
2.2. 函数中可变参数
fn increment(mut num: i32) -> i32 {
num += 1;
num
}
2.3. 可变引用
fn main() {
let mut x = 5;
let y = &mut x;
*y += 1;
println!("{}", x); // 输出 6
}
2.4. 可变结构体
struct Point {
x: i32,
y: i32,
}
fn main() {
let mut p = Point { x: 0, y: 0 };
p.x = 5;
p.y = 10;
println!("Point: ({}, {})", p.x, p.y); // 输出 Point: (5, 10)
}
2.5. 可变元组
let mut tuple = (5, 10);
tuple.0 = 15;
2.6. match 中使用
match Some(10) {
Some(mut value) => {
value += 1;
println!("{}", value); // 输出 11
}
None => {},
}
2.7. 集合中使用
let mut vec = vec![1, 2, 3];
for num in &mut vec {
*num += 1;
}
println!("{:?}", vec);
四、&mut
可变借用引用
&mut
既不属于操作符也不属于关键字
1. 作用
创建一个值的可变引用,允许修改值而不获取所有权。
2. 用法
2.1. 可变引用
fn main() {
let mut x = 10;
{
let y = &mut x; // y 是对 x 的可变引用
*y += 5; // 修改 x 的值
} // y 的生命周期结束,此时 x 的可变借用结束
println!("x: {}", x); // 输出: x: 15
}
2.2. 函数中的可变引用
fn add_one(x: &mut i32) {
*x += 1;
}
fn main() {
let mut a = 10;
add_one(&mut a); // 传递 a 的可变引用
println!("a: {}", a); // 输出: a: 11
}
2.3. 结构体中的可变引用
struct Point<'a> {
x: &'a mut i32,
y: &'a mut i32,
}
fn main() {
let mut x = 10;
let mut y = 20;
let point = Point { x: &mut x, y: &mut y }; // 使用可变引用初始化结构体字段
*point.x += 1;
*point.y += 1;
println!("Point: ({}, {})", point.x, point.y); // 输出: Point: (11, 21)
}
2.4. 集合中的可变引用
fn main() {
let mut vec = vec![1, 2, 3];
for val in &mut vec {
*val += 1; // 修改集合中的元素
}
println!("{:?}", vec); // 输出: [2, 3, 4]
}
2.5. match 中使用
fn main() {
let mut pair = (10, 20);
match pair {
(ref mut x, ref mut y) => {
*x += 1;
*y += 1;
println!("x: {}, y: {}", x, y); // 输出: x: 11, y: 21
},
}
}
2.6. 结构体中使用
struct Counter {
value: i32,
}
impl Counter {
fn increment(&mut self) {
self.value += 1;
}
}
fn main() {
let mut counter = Counter { value: 0 };
counter.increment(); // 使用可变引用调用方法
println!("Counter value: {}", counter.value); // 输出: Counter value: 1
}
五、ref
模式匹配中创建引用
ref
属于关键字
1. 作用
在模式匹配中借用值的不可变引用,而不是获取所有权。
2. 用法
2.1. 元组中使用
fn main() {
let tuple = (1, 2);
let (ref x, ref y) = tuple; // x 和 y 是对 tuple 中元素的不可变引用
println!("x: {}, y: {}", x, y); // 输出: x: 1, y: 2
}
2.2. match 中使用
fn main() {
let pair = (10, 20);
match pair {
(ref x, ref y) => {
println!("x: {}, y: {}", x, y); // x 和 y 是 pair 元素的不可变引用
}
}
}
2.3. if let / while let 中使用
// if let
fn main() {
let some_value = Some(42);
if let Some(ref x) = some_value {
println!("Found a value: {}", x); // x 是 some_value 的不可变引用
}
}
// while let
fn main() {
let mut stack = vec![1, 2, 3];
while let Some(ref x) = stack.pop() {
println!("Popped: {}", x); // x 是 stack 中最后一个元素的不可变引用
}
}
2.4. 函数中使用
fn print_ref((ref x, ref y): &(i32, i32)) {
println!("x: {}, y: {}", x, y); // x 和 y 是元组元素的不可变引用
}
fn main() {
let pair = (10, 20);
print_ref(&pair); // 传递 pair 的引用
}
2.5. for 循环中使用
fn main() {
let vec = vec![1, 2, 3];
for ref x in &vec {
println!("x: {}", x); // x 是 vec 中元素的不可变引用
}
}
六、ref mut
模式匹配中创建可变引用
ref mut
属于关键字
1. 作用
在模式匹配中借用值的可变引用,允许修改该值。
2. 用法
2.1. match 中使用
fn main() {
let mut pair = (10, 20);
match pair {
(ref mut x, ref mut y) => {
*x += 1;
*y += 1;
println!("x: {}, y: {}", x, y); // 输出: x: 11, y: 21
}
}
// pair 的值已经被修改
}
2.2. if let / while let 中使用
fn main() {
let mut some_value = Some(42);
if let Some(ref mut x) = some_value {
*x += 1;
println!("Found a value: {}", x); // 输出: Found a value: 43
}
}
fn main() {
let mut stack = vec![1, 2, 3];
while let Some(ref mut x) = stack.pop() {
*x += 1;
println!("Popped: {}", x); // 输出: Popped: 4, Popped: 3, Popped: 2
}
}
2.3. 函数中使用
fn increment_tuple((ref mut x, ref mut y): &mut (i32, i32)) {
*x += 1;
*y += 1;
}
fn main() {
let mut pair = (10, 20);
increment_tuple(&mut pair); // 传递 pair 的可变引用
println!("pair: {:?}", pair); // 输出: pair: (11, 21)
}
2.4. 解构赋值
fn main() {
let mut pair = (10, 20);
let (ref mut x, ref mut y) = pair;
*x += 1;
*y += 1;
println!("x: {}, y: {}", x, y); // 输出: x: 11, y: 21
println!("{:?}", pair); // (11, 21)
}
七、总结
*
:解引用操作符,用于访问指针或引用指向的值的类型。&
:借用操作符,用于创建不可变引用的类型,允许只读访问。mut
:关键字,用于声明可变变量或参数的类型,允许其值被修改。&mut
:借用操作符,用于创建可变引用的类型,允许读写访问。ref
:模式匹配中的关键字,用于创建不可变引用的类型,避免所有权转移。ref mut
:模式匹配中的关键字,用于创建可变引用的类型,允许修改引用的值。