为何允许转移String所有权,却无法通过*&String实现转移?
两段Rust代码的区别与原因分析
先明确核心前提:String未实现Copy trait,所以它的所有权只能通过**转移(move)**来传递,且转移后原变量会失效。
第一段代码(编译成功)
let greeting = String::from("Hello"); let temp = greeting;
这里是直接对拥有所有权的变量greeting进行赋值操作:Rust会把greeting的所有权完整转移给temp,转移完成后greeting就不再有效(不能被后续代码使用)。这是Rust所有权系统中最基础的合法转移逻辑,完全符合规则。
第二段代码(编译失败)
let greeting1 = String::from("Hello"); let temp1 = *&greeting1;
这里的&greeting1是对greeting1的不可变引用,*&greeting1是对这个引用的解引用——它代表greeting1所指向的String值,但这个值是被借用的,所有权仍然属于greeting1,你只是通过引用临时访问它。
当你尝试把*&greeting1赋值给temp1时,本质是想从一个借用的临时值中转移所有权,但Rust不允许这么做:如果允许,greeting1的所有权会被偷偷转走,但它本身还存在于作用域中,后续代码若再使用greeting1就会访问一个已失去所有权的空壳,这会引发内存安全问题。因此编译器直接报错,禁止这种操作。
额外补充
如果某个类型实现了Copy(比如i32、bool这类简单值类型),那么let temp1 = *&greeting1;是可以编译通过的——因为Copy会直接复制一份新的值给temp1,不会涉及所有权转移,原变量的所有权不受影响。但String是堆分配的复杂类型,无法实现Copy,所以只能遵循严格的所有权转移规则。
内容的提问来源于stack exchange,提问作者mybloodtop
相关产品推荐
相关产品推荐

