Rust 入门 (四)

所有权是 rust 语言独有的特性,它保证了在没有垃圾回收机制下的内存安全,所以理解 rust 的所有权是很有必要的。接下来,我们来讨论所有权和它的几个特性:借用、切片和内存结构。

什么是所有权

Rust 的核心特性是所有权。各种语言都有它们自己管理内存的方式,有些是使用垃圾回收机制,有些是手动管理内存,而 rust 使用的是所有权机制来管理内存。

所有权规则

所有权规则如下:

  • rust 中的每个值都有一个自己的变量。
  • rust 值在同一时间只能绑定一个变量。
  • 变量超出作用域,值会自动被销毁。

不懂没关系,跳过往后看。

变量作用域

rust 语言的变量作用域和其他语言是类似的,看例子:

{                      // 变量 s 还没有被声明,s 在这里是无效的
    let s = "hello";   // 变量 s 是这里声明的,从这里开始生效

    // 从这里开始,可以使用 s 做一些工作
}                      // 变量 s 超出作用域,s 从这里开始不再生效

可以总结两点重要特性:

  • 当变量 s 声明之后开始生效
  • 当变量 s 出了作用域失效

String 类型

在章节三中学习的数据类型都是存储在内存的栈空间中,当它们的作用域结束时清空栈空间,我们现在学习一下内存的堆空间中存储的数据是在何时被 rust 清空的。


我们在这里使用 String 类型作为例子,当然只是简单的使用,具体的内容后文介绍。

let s = "hello";

这个例子是把 hello 字符串硬编码到程序中,我们把它叫做 字符串文字 (string literals 我不知道别人是怎么翻译的,我实在想不到合适的词,先这样叫着吧),字符串文字很方便,但是它不能适用于任何场景,比如我们想要输入一个文本串的时候,原理如下:

  • 字符串文字是不可修改的
  • 编码(编译)时不确定文本串的内容 (比如保存用户的输入)
    在这种情况下,我们会使用字符串的第二种类型——String。它是存储在堆内存中的,而且允许在编译期间不知道字符串的大小,我们先使用 from 函数从字符串文字中创建一个 String 类型的字符串。
let s = String::from("hello");

这种双冒号的语法细节下个章节再说,这里先聚焦于字符串,例子中创建的字符串是可以改变的,比如:

let mut s = String::from("hello");

s.push_str(", world!"); // push_str() 在上个字符串后追加一个字符串

println!("{}", s); // 这里会打印 `hello, world!`

内存分配

字符串文字是在编译期间就有确定的字符内容,所以文本可以直接硬编码到程序中,这就是字符串文字快捷方便的原因。但是字符串文字又是不可变的,我们没办法分配内存给编译期间未知大小及变化的字符串。


字符串类型则支持字符串的修改和增长,即使编译期间未知大小,也可以在堆内存分配一块空间用于存储数据,这意味着:

  • 内存必须是在运行时,从操作系统中请求 (和大多数编程语言类似,当我们调用 String::from 方法时,就完成了对内存的请求)
  • 当不使用这块内存时,我们才会把它返还给操作系统 (和其它语言不同,其它语言是使用垃圾回收机制或手动释放内存)

rust 则是另一种方式:一旦变量超出作用域,程序自动返还内存,通过下面的例子来看这个概念:

{
    let s = String::from("hello"); // s 从这里开始生效

    // 利用 s 做一些事情
}                                  // s 超出作用域,不再生效

当 s 超出作用域,rust 会自动帮我们调用一个特殊的函数—— drop 函数,它是用于返还内存的,当程序执行到 大括号右半块 } 的时候自动调用该函数。

变量和数据交互方式:移动

在 rust 中,可以使用不同的方式在多个变量间交互相同的数据,比如:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值