当前位置: 首页 > ds >正文

Rust 中 i32 与 *i32 的深度解析

Rust 中 &i32*i32 的深度解析

在 Rust 中,&i32*i32 是两种完全不同的指针类型,它们在安全性、所有权和使用方式上有本质区别。以下是详细对比:

核心区别概览

指针类型
引用 &i32
裸指针 *i32
安全
编译器检查
生命周期管理
不安全
手动管理
FFI/底层操作

详细对比分析

1. &i32 - 引用(安全指针)

特性说明
安全性100% 安全,编译器保证有效性
所有权借用检查器控制,不转移所有权
解引用自动解引用(Deref coercion)
使用场景日常 Rust 编程
可变性&i32(不可变)或 &mut i32(可变)
空值永远不为空
别名规则严格遵循借用规则(要么多个不可变引用,要么一个可变引用)
fn safe_ref_example() {let num = 42;let ref_num: &i32 = # // 创建不可变引用// 自动解引用println!("Value: {}", *ref_num); println!("Value: {}", ref_num); // 同样有效// 编译错误:不能同时存在可变和不可变引用// let mut_ref = &mut num;
}

2. *i32 - 裸指针(不安全指针)

特性说明
安全性不安全,需要 unsafe 块操作
所有权无所有权概念,可能悬垂
解引用必须显式解引用(在 unsafe 中)
使用场景FFI、底层系统编程、性能优化
可变性*const i32(不可变)或 *mut i32(可变)
空值可能为空(std::ptr::null()
别名规则无编译时检查,需手动保证安全
fn raw_ptr_example() {let num = 42;let raw_ptr: *const i32 = &num as *const i32;// 必须使用 unsafe 块解引用unsafe {println!("Value: {}", *raw_ptr);}// 可能创建悬垂指针let dangling_ptr: *const i32;{let temp = 100;dangling_ptr = &temp as *const i32;} // temp 离开作用域// 危险:dangling_ptr 现在无效!
}

关键区别详解

1. 安全机制对比

操作
&i32
*i32
编译时检查
借用规则
生命周期验证
运行时风险
悬垂指针
数据竞争

2. 内存访问对比

操作&i32*i32
创建引用/指针&value&value as *const i32
解引用自动或显式 *ref必须 unsafe { *ptr }
空指针不可能std::ptr::null()
指针算术不支持支持(ptr.offset(1)
类型转换有限制(通过 trait)自由转换(as *mut u8

3. 典型使用场景

&i32 场景:
// 函数参数传递
fn print_value(v: &i32) {println!("Value: {}", v);
}// 结构体借用
struct Processor<'a> {data: &'a i32,
}// 迭代器使用
let sum: i32 = vec![1, 2, 3].iter().map(|&x| x * 2).sum();
*i32 场景:
// C 语言交互
extern "C" {fn c_function(ptr: *mut i32);
}// 自定义内存管理
unsafe fn allocate_buffer(size: usize) -> *mut u8 {let layout = std::alloc::Layout::array::<u8>(size).unwrap();std::alloc::alloc(layout)
}// 高性能算法
unsafe fn fast_sum(ptr: *const i32, len: usize) -> i32 {let mut sum = 0;for i in 0..len {sum += *ptr.add(i);}sum
}

转换关系

1. 安全转换

// 引用 → 裸指针(安全)
let num = 42;
let ref_num: &i32 = &num;
let raw_ptr: *const i32 = ref_num as *const i32;

2. 不安全转换

// 裸指针 → 引用(不安全)
unsafe {let ref_back: &i32 = &*raw_ptr;
}

3. 转换注意事项

as *const
unsafe &*
as *const
FFI
Rust调用
安全世界
裸指针
引用
C语言

最佳实践指南

何时使用 &i32

  1. 99% 的日常 Rust 编程
  2. 函数参数传递
  3. 结构体字段借用
  4. 实现 trait 对象 (&dyn Trait)

何时使用 *i32

  1. 与 C 库交互(FFI)
  2. 实现底层数据结构(如自定义分配器)
  3. 极端性能优化场景
  4. 操作系统内核开发

安全使用裸指针的模式:

// 模式1:封装在安全API中
struct SafePointer {ptr: *mut i32,len: usize,
}impl SafePointer {// 安全构造函数pub fn new(data: &mut [i32]) -> Self {SafePointer {ptr: data.as_mut_ptr(),len: data.len(),}}// 安全访问方法pub fn get(&self, index: usize) -> Option<&i32> {if index < self.len {unsafe { Some(&*self.ptr.add(index)) }} else {None}}
}// 模式2:与生命周期绑定
struct GuardedPtr<'a> {ptr: *const i32,_marker: std::marker::PhantomData<&'a i32>,
}impl<'a> GuardedPtr<'a> {pub fn new(reference: &'a i32) -> Self {GuardedPtr {ptr: reference as *const i32,_marker: std::marker::PhantomData,}}pub fn get(&self) -> &'a i32 {unsafe { &*self.ptr }}
}

性能对比

操作&i32*i32
创建开销零成本抽象零成本
解引用开销等同直接访问等同直接访问
安全检查开销编译时(零运行时开销)无检查(需手动验证)
优化潜力编译器充分优化同左,但需更多人工干预

常见错误示例

错误1:悬垂引用

fn dangling_ref() -> &'static i32 {let x = 42;&x // 错误:返回局部变量引用
}

错误2:不安全裸指针使用

fn unsafe_ptr_demo() {let ptr: *const i32;{let value = 100;ptr = &value;} // value 被丢弃unsafe {println!("{}", *ptr); // 未定义行为!}
}

错误3:违反别名规则

fn alias_violation() {let mut data = 42;let ref1 = &data;let ref2 = &mut data; // 错误:同时存在可变和不可变引用println!("{}", ref1);
}

总结对比表

特性&i32*const i32*mut i32
安全性安全不安全不安全
空值不可能可能可能
可变性不可变不可变可变
别名检查严格
生命周期编译器验证无保证无保证
使用场景常规编程FFI/只读访问FFI/写访问
解引用安全unsafeunsafe
自动转换支持 Deref不支持不支持

在 Rust 开发中,优先使用引用 &i32,只有在必要时(如 FFI 或底层系统编程)才使用裸指针 *i32,并且始终将其封装在安全的抽象中。

http://www.xdnf.cn/news/18087.html

相关文章:

  • 解决zabbix图片中文乱码
  • 46.Sentinel规则持久化
  • 8位量化简介(40)
  • 铨林接纸机学习记录1
  • ramdisk内存虚拟盘(一)——前世今生
  • 按键序列常用示例
  • Mini MAX AI应用矩阵测评报告——基于旗下多款产品的综合体验与行业价值分析
  • 六大主流负载均衡算法
  • 分享一个基于Hadoop的二手房销售签约数据分析与可视化系统,基于Python可视化的二手房销售数据分析平台
  • Oracle按照特定列值排序和C#统计特定列值的所有行
  • p5.js 3D盒子的基础用法
  • 【解决笔记】MyBatis-Plus 中无 selectList 方法
  • RK3588消费级8K VR一体机 是否有坑?
  • ABP vNext+ WebRTC DataChannel 低延迟传感推送
  • 《JMeter核心技术、性能测试与性能分析》 教学大纲及标准
  • JavaScript性能优化30招
  • Nacos-5--Nacos2.x版本的通信原理
  • C#---StopWatch类
  • 【开源大模型和闭源大模型分别有哪些?两者的对比?部署私有化模型的必要性有哪些?】
  • 五、ZooKeeper、Kafka、Hadoop、HBase、Spark、Flink集群化软件的部署
  • @Autowired @Resource IDE警告 和 依赖注入
  • 代码随想录刷题Day33
  • C#控制台输入(Read()、ReadKey()和ReadLine())
  • 关于simplifyweibo_4_moods数据集的分类问题
  • 企业级Spring事务管理:从单体应用到微服务分布式事务完整方案
  • 【CUDA 编程思想】FusedQKVProj-分组量化矩阵乘法高效实现全流程解析
  • IT资讯 | VMware ESXi高危漏洞影响国内服务器
  • 软考 系统架构设计师系列知识点之杂项集萃(123)
  • 怎样使用数据度量测试
  • Spring 条件注解与 SPI 机制(深度解析)