枚举中的参数引用

3
下面的代码会出现“无法移动借用的内容”的错误。我知道这里已经有很多关于这个问题的问答了。我觉得所有使用Rust的人都会在某一时刻遇到这个问题,并试图弄清楚归属权是怎么回事。我认为我知道这里发生了什么,以及如何解决它,只是不知道如何在这种特殊情况下使用引用。如果有更符合惯用法的方式来实现我所尝试的,请在评论中告诉我。
我可以看到我正在尝试获取所有权,但我不确定如何使用引用来代替。
让我们看一个比较简单的例子:
/* I define two shape structs. The main point here is that they
 are not default copyable, unlike most primitive types */

struct Circle {
   center_x: f64,
   center_y: f64,
   r: f64,
}

struct Square {
    center_x: f64,
    center_y: f64,
    length: f64,
}

/* this enum will be a container for shapes because we don't know
   which shape we might need. */

enum Shape {
    // these are scoped differently, so it's okay.
    Circle(Circle),
    Square(Square),
}

/* I'm making cookies, each cookie has a shape */
struct Cookie {
    shape: Shape,
}

/* All of the above was setup, here is where we find errors */   

impl Cookie {

    /* checks if two cookies have the same radius. squares -> false */

    fn has_same_radius(&self, other_cookie: &Cookie) -> bool {
    // fn has_same_radius(self, other_cookie: Cookie) -> bool {

    /* swapping the above two lines will remedy the error, 
       but I don't want this function to take ownership of either */

        match self.shape {

            /* As soon as I declare c1, I'm taking ownership of self.shape
               and therefore self as well. This is in spite of the fact
               that I never plan to alter anything. 
               How can I simply use a reference to c1> */

            Shape::Circle(c1) =>  match other_cookie.shape {

                /* same thing here with c2 */
                Shape::Circle(c2) => {
                    if c2.r == c1.r {
                        return true;
                    }
                }
                Shape::Square(_) => return false,

            },
            Shape::Square(_) => return false,
        }
        return false;

    }

}

当我匹配Shape枚举时,我只想引用封装在Shape中的参数,但由于我没有使用引用,所以我试图取得整个Cookie结构体的所有权。


请完整阅读编译器提供的错误信息。该消息显示“帮助:为了防止移动,请使用ref c1ref mut c1通过引用捕获值”。如果您发现错误消息过于混乱,则可以提交问题,描述更好的措辞或错误呈现方式,以使其更清晰易懂。 - Shepmaster
3
@Shepmaster 我花了大约2个小时来弄清楚这个问题。我知道它一定很简单,但当我读到 ref c1 时,作为 Rust 的新手,我立即尝试了 &c1。现在提到了它,我记得在第一次阅读文档时曾经读到过 ref,但我记得没有看到它与 & 不同的任何上下文,并迅速将其放在了脑后。这是那种情况之一,我甚至不知道该问什么问题。现在它已经被解释了,我感到很遗憾,因为错误消息非常有帮助,只是我太傻了。 - Liam
2个回答

5

变更

....
Shape::Circle(c1) => ...
....
Shape::Circle(c2) => ...
....

to

....
Shape::Circle(ref c1) => ...
....
Shape::Circle(ref c2) => ...
....

Playground

let ref x = y;这句话基本上是模式匹配版本的let x = &y;


@Liam,你觉得这个回答或者其他回答解决了你的问题吗?如果是的话,能否接受其中一个回答呢? - WiSaGaN

2

WiSaGan所指出的那样,您必须使用ref模式来创建对包含值的引用。您还可以简化同时匹配两个形状的代码:

impl Cookie {
    fn has_same_radius(&self, other: &Cookie) -> bool {
        match (&self.shape, &other.shape) {
            (&Shape::Circle(ref c1), &Shape::Circle(ref c2))  => c1.r == c2.r,
            _ => false,
        }
    }
}

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