From 4f347355b1cf1c6c098288da96d653c7fd2f5dd6 Mon Sep 17 00:00:00 2001 From: Jesse <35264598+JesseAtSZ@users.noreply.github.com> Date: Tue, 11 Jan 2022 13:10:42 +0800 Subject: [PATCH] Update ownership.md --- book/contents/basic/ownership/ownership.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/book/contents/basic/ownership/ownership.md b/book/contents/basic/ownership/ownership.md index 1077b17a..b9a82b15 100644 --- a/book/contents/basic/ownership/ownership.md +++ b/book/contents/basic/ownership/ownership.md @@ -148,11 +148,11 @@ let s2 = s1; 实际上,`String`类型是一个复杂类型,由存储在栈中的堆指针、字符串长度、字符串容量共同组成,其中堆指针是最重要的,它指向了真实存储字符串内容的堆内存,至于长度和容量,如果你有Go语言的经验,这里就很好理解:容量是堆内存分配空间的大小,长度是目前已经使用的大小. -总之`String`类型的变量指向了栈上的一个地址,而这个地址又指向了一个堆上的空间,堆上存储着它的真实数据, 实现`let s2 = s1`这个拷贝的动作,可能会有下面这两种方式: -1. 拷贝`String`变量在栈上的地址和存储在堆上的真实数据 -如果该语句是拷贝所有数据(深拷贝),那么无论是`String`本身还是底层的堆上数据,都会被全部拷贝,这对于性能而言会造成非常大的影响。 +总之`String`类型指向了一个堆上的空间,这里存储着它的真实数据, 下面对上面代码中的`let s2 = s1`分成两种情况讨论: +1. 拷贝`String`和存储在堆上的字节数组 +如果该语句是拷贝所有数据(深拷贝),那么无论是`String`本身还是底层的堆上数据,都会被全部拷贝,这对于性能而言会造成非常大的影响 -2. 只拷贝`String`变量在栈上的地址 +2. 只拷贝`String`本身 这样的拷贝非常快,因为在64位机器上就拷贝了`8字节的指针`、`8字节的长度`、`8字节的容量`,总计24字节,但是带来了新的问题,还记得我们之前提到的所有权规则吧?其中有一条就是,一个值只允许有一个所有者,而现在这个值(堆上的真实字符串数据)有了两个所有者:`s1`和`s2`。 好吧,就假定一个值可以拥有两个所有者,会发生什么呢? @@ -226,7 +226,7 @@ println!("x = {}, y = {}", x, y); 但这段代码似乎与我们刚刚学到的内容相矛盾:没有调用 `clone`,不过依然实现了类似深拷贝的效果 - 没有报所有权的错误。 -原因是像整型这样的基本类型在编译时已知大小的类型被整个存储在栈上,所以拷贝其实际的值是快速的。这意味着没有理由在创建变量 `y` 后使 `x` 无效(`x`、 `y`都仍然有效)。换句话说,这里没有深浅拷贝的区别,因此这里调用 `clone` 并不会与通常的浅拷贝有什么不同,我们可以不用管它(可以理解成在栈上做了深拷贝)。 +原因是像整型这样的基本类型在编译时是已知大小的,会被存储在栈上,所以拷贝其实际的值是快速的。这意味着没有理由在创建变量 `y` 后使 `x` 无效(`x`、 `y`都仍然有效)。换句话说,这里没有深浅拷贝的区别,因此这里调用 `clone` 并不会与通常的浅拷贝有什么不同,我们可以不用管它(可以理解成在栈上做了深拷贝)。 Rust 有一个叫做 `Copy`的特征,可以用在类似整型这样在栈中存储的类型。如果一个类型拥有 `Copy`特征,一个旧的变量在被赋值给其他变量后仍然可用。