Rust的指针
Rust的指针
- 1: Rust的指针概述
- 2: Rust的引用(Reference)
- 3: Rust的原始引用(Raw Reference)
- 4: Rust的函数指针(Fn Pointer)
- 5: Rust的智能指针(Smart Pointer)
1 - Rust的指针概述
Rust的指针概述
Rust 中将可以表示内存地址的类型成为 指针。
Rust提供了多种类型的指针:
- 引用(Reference)
- 原生指针(Raw Pointer)
- 函数指针(fn Pointer)
- 智能指针(Smart Pointer)
Rust 可以划分为 Safe Rust 和 Unsafe Rust 两部分。
Safe Rust
引用主要应用于 Safe Rust。
在Safe Rust 中,编译器会对引用进行借用检查,以保证内存安全和类型安全。
Unsafe Rust
原生引用主要用于 Unsafe Rust。
原生引用不在 Safe Rust 的控制范围内,需要编程人员自己保证安全。
2 - Rust的引用(Reference)
Rust的引用(Reference)
Rust 提供引用操作符 &
,可以直接获取表达式的存储单元地址,即内存地址。
引用本质上是一种非空指针。
let a = [1,2,3];
let b = &a;
println!("{:p}", b); // 0x7ffcbc067704
// 要获取可变引用,必须先声明可变绑定
let mut c = vec![1,2,3];
// 通过 &mut 得到可变引用
let d = &mut c;
d.push(4);
println!("{:?}", d); // [1, 2, 3, 4]
let e = &42;
assert_eq!(42, *e);
从语义上说,不管是 &a
还是 &mut c
,都是对原有变量的所有权的借用,所以引用也被称为借用。
3 - Rust的原始引用(Raw Reference)
Rust的原始引用(Raw Reference)
Rust 支持两种原始引用:
- 不可变原始指针
*const T
- 可变原始指针
*&mut T
用 as 操作符可以将引用转为原始指针:
let mut x = 10;
let ptr_x = &mut x as *mut i32;
let y = Box::new(20);
let ptr_y = &*y as *const i32;
// 原生指针操作要放在unsafe中执行
unsafe {
*ptr_x += *ptr_y;
}
assert_eq!(x, 30);
4 - Rust的函数指针(Fn Pointer)
Rust的函数指针(Fn Pointer)
函数在Rust中是一等公民,函数自身就可以作为函数的参数和返回值使用。
函数作为参数
```
/// 将函数作为参数传递
pub fn math(op: fn(i32, i32) -> i32, a: i32, b: i32) -> i32{
/// 通过函数指针调用函数
op(a, b)
}
fn sum(a: i32, b: i32) -> i32 {
a + b
}
fn product(a: i32, b: i32) -> i32 {
a * b
}
let a = 2;
let b = 3;
assert_eq!(math(sum, a, b), 5);
assert_eq!(math(product, a, b), 6);
```
函数作为返回值
fn is_true() -> bool { true }
/// 函数的返回值是另外一个函数
fn true_maker() -> fn() -> bool { is_true }
/// 通过函数指针调用函数
assert_eq!(true_maker()(), true);
```
5 - Rust的智能指针(Smart Pointer)
Rust的智能指针(Smart Pointer)
智能指针 (Smart Pointer) 源自c++,Rust 引入后成为 Rust 语言中最重要的一种数据结构。
功能介绍
Rust 中的值默认被分配到 栈内存。可以通过 Box<T>
将值装箱(在堆内存中分配)。
Box<T>
是指向类型为T的堆内存分配值的智能指针。- 当
Box<T>
超出作用域范围时,将调用其析构函数,销毁内部对象,并自动释放内存。 - 可以通过解引用操作符来获取
Box<T>
中的T
Box<T>
的行为像引用,并可以自动释放内存,所以称为智能指针。
Box<T>
类型
Rust 中提供了很多智能指针类型。
#[derive(Debug, PartialEq)]
struct Point {
x: f64,
y: f64,
}
let box_point = Box::new(Point { x: 0.0, y: 0.0 });
let unboxed_point: Point = *box_point;
assert_eq!(unboxed_point, Point { x: 0.0, y: 0.0 });