Rust能力养成系列之(33):内存管理:所有权初探

本文深入探讨Rust编程语言的核心特性——所有权、借用和生命周期,解释了如何通过这些机制确保内存安全。Rust的独特所有权规则规定每个值只有一个所有者,当值从一个变量转移到另一个变量时,原始变量将变得无效。这一原则避免了内存泄漏和迭代器失效等问题,提供了一种在编译时防止这些问题的安全机制。文章通过示例展示了所有权规则的应用,并预告了后续将讨论变量作用域的影响。
摘要由CSDN通过智能技术生成

前言

我们接下来要探讨的概念是Rust的内存安全性的核心原则及其零成本抽象原则,这写原则使Rust能够在编译时,检测到程序中的内存安全违规行为,并在相应的作用域结束时自动释放资源,等等。我们称这些概念为所有权、借用和生命周期(ownership, borrowing, and lifetimes)。在这三者中,以所有权为核心原则,而借用和生命周期是Rust类型系统的扩展,在代码的不同上下文中调整所有权原则,可以确保编译时内存管理。下面,就让我们来详细阐述一下这些概念。

程序中资源的真正所有者(a true owner of a resource)的概念因语言而异。在这里,我们可以统称为保存堆或栈上的任何变量,或者保存打开的文件描述符、数据库连接套接字、网络套接字等类似内容的变量。从它们存在的那一刻起,直到被程序使用完毕,都会占用一些内存。作为资源所有者,其一项重要的职责,就是在合适的场合释放使用的内存,否则很可能会导致内存泄漏(memory leaks)。

在用动态语言(如Python)中编程时,一个列表对象有多个所有者或别名是很常见的,开发者可以使用指向该对象的多个变量之一来添加或删除列表项,而不需要关心释放对象所使用的内存,因为垃圾采集器GC会对此负责,一旦对对象的所有引用都消失了,GC就会释放内存。

对于像C/ C++这样的编译性语言,在智能指针出现之前,有关代码在资源使用完成后,是由被调用者还是调用者负责释放内存,存在争议。这些观点之所以存在,是因为在这些语言中,编译器并没有强制所有权。在C++中因为不使用智能指针而出错的情况很多,比如,当有多个变量指向堆上的一个值是完全没问题的(尽管不建议这样做),这被称为混叠(aliasing)。一个资源使用多个指针或别名的灵活性,固然很有灵活性,处理不好的话,也会给程序员会造成各种不良影响,其中之一就是C++中的迭代器失效问题,前面已经解释过了。具体来说,当给定范围内的其他不可变(绑定)别名中至少有一个资源的可变(绑定)别名时,就会出现问题。

铺陈许久,引出我们的主角,Rust,为程序中的值的所有权,尽可能的设置适当语义。原则如下:

  • 当使用let语句创建一个值或资源并将其分配给一个变量时,该变量将成为资源的所有者
  • 当值从一个变量重新分配给另一个变量时,该值的所有权转移到另一个变量,旧变量失效,不可以再供进一步使用
  • 值和变量在作用域结束时被重新分配

结论是Rust中的值只有一个所有者,即创建它们的变量。这个原理很简单,但其含义着实让来自某些其他语言的程序员感到过惊讶。考虑下面的代码,其以最基本的形式演示了所有权原则:

// ownership_basics.rs

#[derive(Debug)]
struct Foo(u32);

fn main() {
    let foo = Foo(2048);
    let bar = foo;
    println!("Foo is {:?}", foo);
    println!("Bar is {:?}", bar);
}

看下代码,我们创建了两个变量,foo和bar,它们指向一个foo实例。对于熟悉类似Python这种允许一仆多主的语言的人而言,习惯上希望这个程序能够很好的编译。但是在Rust中编译时,会得到以下错误

这里解释几句,我们创建了一个Foo实例,并将它分配给Foo变量。根据所有权规则,foo现在是foo实例的所有者。在下一行中,又将foo赋值给bar。在执行main的第2行时,bar成为Foo实例的新所有者,旧的Foo现在是一个被放弃的变量,已经不能在任何地方使用,所以在println!宏语句中就过不去了。

当我们将某个变量赋值给其他变量或从该新变量中进行读取时,Rust就会改变原来的所有权。所有权规则禁止使用多个访问点来进行值修改,这会使得以往在C/C++语言中可以侥幸用一用的脏活儿,不再有打擦边球的可能。比如之前提及的C++中的迭代器失效问题,可以在编译阶段直接规避。

 

结语

以上介绍了所有权的基本内容,但尚未完,所有权规则还考虑了变量的作用域。那么,为了分析一个值何时超出作用域,请看下篇分解。

 

主要参考和建议读者进一步阅读的文献

https://doc.rust-lang.org/book

Rust编程之道,2019, 张汉东

The Complete Rust Programming Reference Guide,2019, Rahul Sharma,Vesa Kaihlavirta,Claus Matzinger

Hands-On Data Structures and Algorithms with Rust,2018,Claus Matzinger

Beginning Rust ,2018,Carlo Milanesi

Rust Cookbook,2017,Vigneshwer Dhinakaran

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值