Rust

Rust String

2019-11-08  本文已影响0人  空乱木

原文链接:https://learnku.com/docs/rust-lang/2018/ch04-01-what-is-ownership/4505

1- 移动

变量移动

let s1 = String::from("hello”);
let s2 = s1;

String由三部分组成

将值 "hello" 绑定给 s1 的 String 在内存中的表现形式:


image.png

当我们将 s1 赋值给 s2,String 的数据被复制了,这意味着我们从栈上拷贝了它的指针、长度和容量。我们并没有复制指针指向的堆上数据。

变量 s2 的内存表现,它有一份 s1 指针、长度和容量的拷贝:


image.png

之前我们提到过当变量离开作用域后,Rust 自动调用 drop 函数并清理变量的堆内存。不过图 4-2 展示了两个数据指针指向了同一位置。这就有了一个问题:当 s2 和 s1 离开作用域,他们都会尝试释放相同的内存。这是一个叫做 二次释放(double free)的错误,也是之前提到过的内存安全性 bug 之一。两次释放(相同)内存会导致内存污染,它可能会导致潜在的安全漏洞。

为了确保内存安全,这种场景下 Rust 的处理有另一个细节值得注意。
与其尝试拷贝被分配的内存,Rust 则认为 s1 不再有效,因此 Rust 不需要在 s1 离开作用域后清理任何东西。看看在 s2 被创建之后尝试使用 s1 会发生什么;这段代码不能运行:

let s1 = String::from("hello”);
let s2 = s1;

println!("{}, world!", s1);

Rust 禁止你使用无效的引用:

error[E0382]: use of moved value: s1
--> src/main.rs:5:28
|
3 | let s2 = s1;
| -- value moved here
4 |
5 | println!("{}, world!", s1);
| ^^ value used here after move
|
= note: move occurs because s1 has type std::string::String, which does
not implement the Copy trait

最终的复制-移动结果如下:

2- 克隆

当出现 clone 调用时,你知道一些特定的代码被执行而且这些代码可能相当消耗资源。你很容易察觉到一些不寻常的事情正在发生。

let s1 = String::from("hello”);
let s2 = s1.clone();

println!("s1 = {}, s2 = {}", s1, s2);

image.png

变量的所有权总是遵循相同的模式:将值赋给另一个变量时移动它。

上一篇下一篇

猜你喜欢

热点阅读