这段代码无法编译:
fn main() {
let x = "".to_string();
let y = &x;
let z = *y;
}
编译器错误输出为:
我不太清楚这里发生了什么,需要解释一下。无法移动共享引用后面的
*y
移动发生的原因是
*y
具有类型String
,它没有实现Copy
特性
我原本希望
z
拥有这个 String
的所有权,使得 x
和 y
变得无法使用。这段代码无法编译:
fn main() {
let x = "".to_string();
let y = &x;
let z = *y;
}
我不太清楚这里发生了什么,需要解释一下。无法移动共享引用后面的
*y
移动发生的原因是
*y
具有类型String
,它没有实现Copy
特性
z
拥有这个 String
的所有权,使得 x
和 y
变得无法使用。let z = *y;
y
,而 y
是一个 &String
。 &String
不包含任何关于它来自哪里的信息,它只包含它是一个指向 String
的引用的信息。它不知道也不关心 x
包含的实际内容,除了借用检查器确保 x
保持在作用域内且不可变之外,它对 x
没有任何控制权。*y
实际上并没有生成 x
,而是一个匿名的 String
值,只能通过引用访问,这意味着它可以使用,但不是所有者。z = *y
,您正在尝试拥有引用后面的值。但正如我所说,这将需要修改 x
(因为之后它不再有效),而 y
对 x
没有任何权限。因此,这是不可能的。z = *y
并不是问题,因为它们不需要转移所有权,而只需进行复制,Rust 通知您这是不可能的,因为 y
引用的值没有实现 Copy
。*y
不同于 x
。但是 y
并不是在栈上取 x
的地址作为自己的值吗?我一直在考虑 C/C++ 中的指针,但 Rust 强制实施了自己的所有权和借用语义? - TSKunsafe
关键字。 - Finomnisz = *y
实际上影响了x
变量。只是现在还没有达到那个程度。编写借用检查器是一项艰苦的工作,在你的特定情况下,做*y
毫无意义,因为你可以简单地做z = x
。而在所有其他情况下,当你无法轻松访问原始变量x
时,绝对不要允许人们移出y
。 - FinomnisString
值”被称为一个_占位符_。 - Chayim Friedman我有不同的理解。但是我的理解可能是错误的。 通过解引用运算符(*y),会生成一个无名临时变量。这个临时变量与 x(let x = "".to_string();)不同,它不获取所有权。 (let z = *y;)=> 移动了临时变量,但没有所有者。所以出现错误。
https://rustwiki.org/en/reference/expressions.html#moved-and-copied-types
z
接管String
的所有权?你可以从拥有的内容中借用,但是你不能从借用的内容中拥有一个对象。 - Ömer Erdeny
在执行完*y
和*y
是x
后,当其所有权转移到z
时,x
就没有借款人了?但这似乎不是 Rust 的工作方式。我猜想(没有证据)在整个语句完成之前,y
仍然在作用域内。 - TSK*y
并不完全等同于x
,x
仍然存在并由当前函数的作用域拥有。*y
,即*&x
,允许您访问指向内存位置(&x
)中的值。如果您尝试进行赋值,则会尝试移动该值,但该值的所有者是x
。如果Rust允许您移动它,那么x
会发生什么? - Ömer Erden