所有权和借用
所有权
所有的程序都必须和计算机内存打交道,如何从内存中申请空间来存放程序的运行内容,如何在不需要的时候释放这些空间,总共有三种流派: - 垃圾回收机制,在程序运行时不断寻找不再使用的内存。 - 手动管理内存的分配和释放,在程序中,通过函数调用的方式来申请和释放内存。 - 通过所有权来管理内存,编译器在编译时会根据一系列规则来检查。
栈和堆
栈和堆的核心目标就是为程序的运行时提供可供使用的内存空间
栈
栈按照顺序存储值并以相反顺序取出值,这也被称作后进先出。 增加数据叫做进栈,移出数据叫做出栈 栈中的所有数据度必须占用已知且固定大小的内存空间。
堆
预展不同,对于大小位置或者可能变化的数据,我们需要将它存储在堆上。 当向堆放入数据时,需要请求一定大小的内存空间。操作系统在堆的某处找到一块足够大的空位,把它标记为己使用,并返回一个表示该位置地址的指针,该过程被称为在堆上分配内存。接着,该指针会被推入栈中,因此指针的大小是已知且固定的。
所有权原则
原则: 1. Rust 中每一个值都被一个变量所拥有,该变量被称为值得所有者 2. 一个值同时只能被一个变量所拥有,或者说一个值只能拥有一个所有者 3. 当所有者离开作用域范围时,这个值将被丢弃
变量绑定背后的数据交互
转移所有权
String
类型是一个复杂类型,由存储在栈中的堆指针、字符串长度、字符串容量共同组成,其中堆指针是最重要的,它指向了真实存储字符串内容的堆内存。
引用与借用
获取变量的引用,称之为借用
引用与解引用
常规的引用是一个指针类型,指向了对象存储的内存地址。必须使用 *x
来解出引用所指的值(也就是解引用)。
不可变引用
&
符号即是引用,它们允许代码使用值,但是不获取所有权。这样可以带来的好处是:无需先通过函数参数传入所有权,然后在通过函数返回来传出所有权,代码更加简洁
通过 $
语法,我们创建一个指向变量的引用,但是并不拥有它。因为并不拥有这个值,当引用离开作用域后,其指向的值也不会被丢弃。
可变引用
可变引用同时只能存在一个 可变引用的限制:同一作用域,特定数据只能有一个可变引用。这种限制的好处就是使 Rust 在编译期就避免数据竞争,数据竞争可由以下行为造成: - 两个或更多的指针同时访问同一数据 - 至少有一个指针被用来写入数据 - 没有同步数据访问的机制 数据竞争会导致未定义行为,这种行为很可能超出我们的预期,难以在运行时跟踪,并且难以诊断和修复。而 Rust 避免来这种情况的发生,因为它甚至不会编译存在数据竞争的代码。
可变引用与不可变引用不能同时存在 引用作用域的结束位置为最后一次使用的位置。