Rust 结构体引用的解构 vs 结构体解构

6
以下代码能正常运行。
#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32
}

fn area(shape: &Rectangle) -> u32 {
    let Rectangle{width, height} = shape;
    width * height
}

fn main() {
    let rec1 = Rectangle {width: 5, height: 10};
    println!("Area {}", area(&rec1));
    println!("Rec {:?}", rec1);
}

将结构体&Shape的引用替换为解引用引用*&Shape也可以工作(例如:let Rectangle{width, height} = shape; --> let Rectangle{width, height} = *shape;)。

我不知道为什么两个都能工作,难道在解构时有一些隐式的解引用操作吗?我认为&Shape引用只是指向Shape在内存中的位置,而*&ShapeShape本身。widthheightstruct Rectangle的属性,而不是引用&Rectangle


你不是在创建一个名为rec1的新矩形(它是shape的副本),而不是解构吗?如果你想要解构,你需要使用match。请参见Rust by Example - hkBst
1
@hkBst let 也执行模式匹配,但只允许不可反驳的模式。代码确实对shape进行了解构,这不是问题所在。 - Masklinn
2个回答

12
我不知道为什么两者都可以工作,难道在解构时有一些隐式的解引用吗?
这是2018版的匹配人性化的一个(方便但令人困惑的)结果:当匹配引用类型时,编译器会隐式添加引用和解引用,以使事情正确。
area中发生的是widthheight&u32而不是u32,编译器有效地将您的代码解释为:
let &Rectangle{ ref width, ref height } = shape;

如果你没有使用像rust-analyzer这样的工具,可以直接在编辑器中显示这些信息,一个常见的技巧是写一些类似于:

let x: () = var

编译错误将告诉您var的类型(除非它是() )。

我认为,&Shape引用只指向Shape在内存中的位置,而*&Shape是Shape本身。

这是正确的,但是在模式的上下文中,并不一定意味着该结构被移动。由于Rectangle的字段都是Copy类型,编译器可以对“拥有”的结构进行解构,而不需要移动它,它可以直接复制字段。这本质上就是简单属性访问所做的(shape.widthu32)。


1
实际上,我在Rust 2021中尝试过这个,rust-analyzer告诉我,我得到了两个引用:`wdith`和`height`。所以我看了一下`width * height`这一行,有两个对u32的引用,以及`*`运算符,也就是`std::ops::Mul`已经实现了两个`&u32`的乘法。

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