Rust所有权机制和内存安全详解

Rust所有权机制的设计是这门语言的最大特点,也是其内存安全多线程并发安全的基石。

本文先来探讨一下Rust的所有权机制和内存安全。

1. 先来定义一个基础类Point

struct Point {
    x: i32,
    y: i32,
}

struct从C语言借鉴而来,用来定义一个结构体。

Point结构体中包含x和y两个32位int类型的成员。

2. 所有权机制的核心概念

一块内存在同一个时刻,只会有一个所有者;如果进行赋值,或者函数传参、从函数返回等,所有权就会发生变更。

fn test_ownership() {
    // 只读的p1指向一个在栈上分配的Point结构
    let p1 = Point { x: 25, y: 25 };
    
    // 将p1指向的point的所有权转移给p2
    let p2: Point = p1;

    // p1已无效,只能通过p2进行访问
    println!("{} {}", p2.x, p2.y);
}

let声明的变量默认是read-only,类比java中的final。如果要修改内存中的值,需要借助mut关键字进行声明。

fn test_mut() {
    // 想要修改变量指向的内存,需要mut关键字配合
    let mut p1 = Point { x: 25, y: 25 };
    p1.x = 30;
    println!("{} {}", p1.x, p1.y);
}

只读变量如果想要作为参数传入一个函数,需要通过&符将变量的使用权借用到一个函数里面。

Rust中的借用类比C里面的引用,只是rust中的这个“引用”,不具有所有权。

fn test_borrow() {
    let p1 = Point { x: 25, y: 25 };
    // 通过&符将原数据的使用权,借用到borrowReadOnly()函数里面
    borrowReadOnly(&p1);
    // p1仍然具有所有权
    println!("{}", p1.x);
}
// p是只读借用,f里面不能修改p.x/p.y
// p并不具有所有权,不会延长原数据的生命周期
fn borrowReadOnly(p: &Point) {
	println!("{}", p.x);
}

如果想要在函数里面,修改传参变量所引用的内存,需要借助mut。

// 可写借用,借用者可以对内存进行修改
// 借用只是一个使用权,并不具备所有权
fn test_mut_borrow() {
    let mut p = Point { x: 25, y: 25 };
    borrowWritable(&mut p);
    println!("{}", p.x);// 100
}
fn borrowWritable(p: &mut Point) {
    p.x = 100;
}

可写的借用必须3个地方都同时加mut才行:p变量声明、函数参数签名、函数调用传参。

3. 总结

  1. Rust语言通过所有权机制的设计,严格限定一块内存在同一个时刻只会被一个变量拥有所有权
  2. 编译器只需要跟踪具有所有权的变量的生命周期,并在所有权终结时释放相应的内存。
  3. 由于借用不会延长变量的生命周期,所以rust中不会出现野指针(比如,访问已经释放的内存)等内存错误,从而保证了内存安全。

4. 完整测试代码

//所有权测试 ---- 一块内存在同一个时刻,只会有一个所有者
fn test_ownership() {
    // p1指向的point是分配在栈上的
    let p1 = Point { x: 25, y: 25 };
    // 将p1指向的point的所有权转移给p2
    let p2: Point = p1;

    // p1已无效,只能通过p2进行访问
    println!("{} {}", p2.x, p2.y);
}

//mut(mutable)关键字测试
fn test_mut() {
    // let声明的变量默认是read-only,类似java中的final
    // 想要修改需要mut关键字配合
    let mut p1 = Point { x: 25, y: 25 };
    p1.x = 30;
    println!("{} {}", p1.x, p1.y);
}

// &表示借用(类似于C/C++中的取地址、引用),借用而已,不具有所有权
// 只读借用,借用者只能读,不能写
fn test_borrow() {
    let p1 = Point { x: 25, y: 25 };
    borrowReadOnly(&p1);
    // 所有权并未转移,依然归p1
    println!("{}", p1.x);
}
// 只读借用,f里面不能修改p.x/p.y
fn borrowReadOnly(p: &Point) {
	println!("{}", p.x);
}

fn test_mut_borrow() {
    let mut p = Point { x: 25, y: 25 };
    // 可写借用,借用者可以对内存进行修改
    borrowWritable(&mut p);
    // 但所有权仍归p
    println!("{}", p.x);
}
fn borrowWritable(p: &mut Point) {
    p.x = 100;
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值