4

Rust所有权与借用图示概念

 1 year ago
source link: https://www.jdon.com/62823
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Rust所有权与借用图示概念


Rust 中的所有权是什么?
Rust没有垃圾收集器,您需要显式分配和释放内存空间。当涉及大型代码库时,这很快就会变得乏味和具有挑战性。
传统上,有两种管理内存的基本方法:

  • 第一个是垃圾收集器;它主要用于从程序员那里抽象出内存管理概念的高级语言中。
  • 第二种是手动内存管理,程序员明确定义内存使用。虽然它提供了控制,但它留下了很大的空间让自己在脚下开枪。

Rust 采用了另一种方法,称为所有权和借用。所有权是一种新的结构,它定义了一个值  且有一个所有者。

让我们看看下面这段代码和它的输出

v2-d216952d2dfb25006d79d2a1811aa4b0_720w.png

change the value of i=11
print the value of i=10, after let_change_the_value_by_one call

当我们将i传递给函数let_change_the_value_by_one时,将值增加1并打印它,当控件返回main() 函数并打印它时,我们得到与以前相同的值。

v2-51df7891e679fd38e3051a80a1f8e2b9_720w.png

与字符串String不同, 整数存储在栈Stack中而不是堆Heap中,当把i传给函数let_change_the_value_by_one时,编译器会复制一个值并把它传给函数,实际值保持不变。在所有权方面,变量i是栈中数值的所有者,在其作用域内一直保持有效。
现在,我们如何将变量从更改i8为string发生的情况

v2-2a018fc95763b9caed9eb7ba149380fd_720w.png
18 |     let value_for_i = String::from("Rust");
   |----------- move occurs because `value_for_i` has type `String`, which does not implement the `Copy` trait
19 |     lets_change_the_value_of_string(value_for_i);
   |----------- value moved here
20 |     println!("print the value of value_for_i={}, after lets_change_the_value_of_string call", value_for_i)
   |                                                                                               ^^^^^^^^^^^ value borrowed here after move

现在当涉及到Heap堆时,所有权的概念将更加透明。
当变量value_for_i传递给函数lets_change_the_value_of_string时,编译器在Stack栈中创建了一个变量引用的副本,并将所有权转移到它。
Heap堆中的值没有发生任何变化。一旦控制权回到main(),变量value_for_i的引用就不存在了,这就是编译器试图告诉我们移动已经发生的原因。

|----------- 发生移动是因为 `value_for_i` 的类型为 `String`,它没有实现 `Copy` 特征
| let_change_the_value_of_string(value_for_i); 
|----------- 值已移至此处

这是原理插图:

v2-b7685885e18305e3ad5a73702a169210_720w.png

简而言之,Rust作用域内的任何变量都是值的所有者,它不能在其所有权之外更改。所有权需要由程序员自己手动管理。
为了使这段代码工作,我们可以将value_for_i.clone()传递给函数,这将创建一个引用和值的克隆。

v2-d6cfbeab33a885bf61e420e0d187c124_720w.png

但是,如果我们不想转移所有权而是想修改相同的值怎么办。通过使用借贷的概念如何实现这一点

Rust中的借用是什么
在Rust中,我们可以从Stack中借用变量的引用,然后使用借用的引用对Heap中的值执行操作。这样我们就完全不用处理所有权的转移。为了借用value_for_i的引用,我们使用借用操作符&,把像&value_for_i这样的引用借用传递给函数。 

v2-4c1a28ef6d10ee842efa07be6b58868a_720w.png
print the value of value_for_i=Rust, before lets_change_the_value_of_string call
The value of variable value_for_i=Rust is awesome
print the value of value_for_i=Rust is awesome, after lets_change_the_value_of_string call

上面的例子我们正在做很多事情:

  1. 将局部变量value_for_i改为可变
  2. 将函数的参数改为&mut value_for_i , 这样就可以传递引用,同时也使其成为可变的。
  3. 使用push_str()和value_for_i来扩展字符串的值。
  4. 现在当控件回到main()并执行println!时,我们得到了修改后的字符串。

这解释了我们如何使用借用概念来处理我们不想转移所有权的价值。虽然借用概念有一些限制。

v2-ac6cdb5fee676aee63383da9f108d5bd_720w.png
v2-70bc837757a94a60dc7eda257e2bb919_720w.png

我们只能在其作用域内为变量创建一次可变引用。不可变引用没有限制。如果发现悬空引用,编译器也会抱怨,这意味着编译器将确保数据在引用之前不会超出作用域。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK