2016-05-17 111 views
1

下面的代码给出错误“无法移出借用内容”。我知道这里有很多关于这方面的问题。我认为每个使用Rust的人都会发现自己在某个地方,试图弄清楚所有权究竟发生了什么。我想我知道这里发生了什么,以及如何解决它,我只是不知道如何在这个特定情况下使用参考。如果有更习惯的方式来完成我所尝试的,请在评论中告诉我。参考enum中的参数

我可以看到我想要拥有所有权,但我不确定如何使用参考。

让我们看一个有点小例子:

/* 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结构的所有权。

+0

请完整阅读编译器提供的错误消息。消息说:“帮助:为了防止移动,使用'ref c1'或'ref mut c1'来通过引用捕获值。如果您发现错误消息太混乱,请[提出问题](https://github.com/rust-lang/rust)描述更好的措辞或错误的表述会使错误更加明确。 – Shepmaster

+1

@Shepmaster我花了大约2个小时试图弄清楚这一点。我知道它必须是简单的,但是当我阅读'ref c1'时,我对Rust很陌生,立即尝试'&c1'。现在已经提到过了,当我第一次浏览文档时,我确实记得在文档中阅读过'ref',但是我记得没有看到与'&'不同的任何上下文,并立即将它放在脑海中。这是我真的不知道要问的正确问题的其中一种情况。现在已经解释了,我在踢自己,因为错误信息非常有帮助,我只是哑巴。 – Liam

回答

3

变化

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

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

Playground

let ref x = y;是基本上匹配的let x = &y;版本的图案。

+0

@Liam你觉得这个还是其他答案你的问题?如果是这样,你能接受一个答案吗? – WiSaGaN

1

正如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, 
     } 
    } 
}