在比赛中使用ref和与非引用匹配之间有区别吗?

问题描述

这两个match分支是否等效?

struct Quux { wibble: u8 }

enum Foo { 
    Bar(Quux),Baz(Quux),}

impl Foo {
    pub fn quux(&self) -> &Quux {
        match self {
            Foo::Bar(ref quux) => quux,Foo::Baz(quux) => &quux,}
    }
}

如果是,为什么ref存在?

解决方法

当我们匹配而不是引用时,它们确实有所不同。考虑示例:

enum Foo { 
    Bar(i32),Baz(i32),}

fn main() {
    // bar is a value.
    let bar = Foo::Baz(13);

    // Uncomment line below to make bar become a reference.
    //let bar = &bar;
    
    let i = match bar {
        Foo::Bar(ref x) => x,Foo::Baz(x) => &x,};
    println!("{}",i);
}

编译出现错误

error[E0597]: `x` does not live long enough
  --> src/main.rs:15:24
   |
13 |     let i = match bar {
   |         - borrow later stored here
14 |         Foo::Bar(ref x) => x,15 |         Foo::Baz(x) => &x,|                        ^-
   |                        ||
   |                        |`x` dropped here while still borrowed
   |                        borrowed value does not live long enough

x分支中的Foo::Baz(x)拥有i32内部Baz的所有权,并被丢弃在分支的末端。这就是i不能借用x,寿命不足的原因。另一方面,x分支中的Foo::Bar(ref x)没问题,因为它只是借用i32内部的Bar

但是,如果我们取消注释let bar = &bar;行,则bar将成为引用,并且ref将自动插入到每个分支中(根据rust reference)。这样就可以编译。

在您的代码中,由于quux借用了selfquux(&self))而不是拥有所有权(quux(self)),这意味着{{ 1}}是参考,因此可以编译。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...