在Rust中,为什么`a`在`let b = &*&a;`之后仍然拥有所有权?

7

我发现&(*&a)&{*&a}的行为不同,这让我感到困惑。

具体来说,以下代码无法编译:

struct CanNotCopy;
fn main(){
    let a = CanNotCopy;
    &{*&a};
    let c = a;
}

以下代码已编译:

struct CanNotCopy;
fn main(){
    let a = CanNotCopy;
    &(*&a); // or &*&a;
    let c = a;
}

以上代码的语义差异是什么?

哪些语言构造确切地导致了所有权的转移?


1
()和{}本身就不同,前者只是修改操作顺序,而后者则创建一个新的嵌套作用域。 - Netwave
1
@Netwave 感谢您的评论。我知道 (){} 在概念上是不同的,但更精确的描述(例如传递所有权的语言结构列表)将使事情更清晰。很抱歉我已经尝试过了,但并没有在互联网上找到这样的材料。语言参考手册肯定会描述这些内容,但对于初学者来说阅读语言参考手册太难了。 - yslking
在 Rust 中,块表达式是一个表达式,它由花括号包围的语句序列组成。块表达式可以出现在任何需要表达式的地方。块表达式的值是最后一个表达式的值,或者如果没有表达式,则为 ()。块表达式中的变量绑定只在该块内部可见。 - Masklinn
1个回答

6

通过使用{},你将a移动到一个新的作用域中,然后进行引用和取消引用。这也可以简化为:

struct CanNotCopy;
fn main(){
    let a = CanNotCopy;
    {a};
    let c = a;
}

你可能会遇到同样的问题,现在让我们转向另一个问题。假设您在作用域之前有一个引用:
struct CanNotCopy;
fn main(){
    let a = CanNotCopy;
    let aa = &a;
    {aa};
    let c = a;
}

这是行得通的,因为我们只是移动引用而不是原始对象本身。

那么关于 *& 的操作呢:

struct CanNotCopy;
fn main(){
    let a = CanNotCopy;
    let aa = &a;
    &{*aa};
    let c = a;
}

由于上面提到的原因,我们遇到了一个无法移动在共享引用后面的*aa的错误。

在同一作用域内使用()时,我们不会遇到这个错误,因此那里没有真正的移动。

编辑(摘自评论):有些相关问题:


感谢 @Netwave 的答案。以下链接可能对和我有类似困惑的人有所帮助:1. https://dev59.com/z1MI5IYBdhLWcg3wM4h0; 2. https://dev59.com/8Lroa4cB1Zd3GeqPq8b8 - yslking

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接