【问题标题】:Passing structures as arguments in Rust在 Rust 中将结构作为参数传递
【发布时间】:2021-08-16 01:00:12
【问题描述】:

我正在用 Rust 从头开始​​构建一个图形引擎。
我有一个结构点:

struct Point {
  x: i32,
  y: i32
}

还有一个三角形结构,就是三个点:

struct Triangle (Point,Point,Point)

.

我制作了一个特征引擎,稍后我将使用 SDL 实现它

trait Engine {
  fn draw_triangle(&self,tri:Triangle){
     self.draw_line(tri.0,tri.1);
     self.draw_line(tri.1,tri.2); // <-
     self.draw_line(tri.2,tri.0);
  }
  fn draw_line(&self,p1:Point,p2:Point)

}

我得到一个带有箭头的错误:使用移动的值 tri.1,移动后使用的值。
我知道这与引用和所有权有关,并且尝试过改变事物,但我只是不知道自己在做什么。
我找了又找,但无济于事:我无法理解。

谁能告诉我为什么这不起作用?不仅仅是一个解决方案,我希望了解

【问题讨论】:

  • 欢迎来到 StackOverflow!你读过关于 Rust 的书吗,比如官方的书,或者 O'Reilly 的《Programming Rust》?两者都很好地解释了 moving 的概念,足以让您理解解决方案(如您所愿)。解决办法是在struct Point的定义上面加上#[derive(Copy, Clone)]。它将使Point 的行为更像一个非常简单的原始对象(如数字或布尔值),允许通过复制而不是移动将其传递给函数。

标签: struct rust reference ownership


【解决方案1】:

在第一个 draw_line 调用中,您通过了两个点 tri.0 和 tri.1。这会将变量“移动”到draw_line 函数中,之后就不能使用它们了。有两种方法可以解决此问题。

首先,您可以在调用函数时复制(或克隆)这些点,只需在struct Point 行上方添加#[derive(Clone, Copy)]。这允许点被显式克隆(通过使用.clone() 方法)或隐式复制。这意味着每次将数据传递给函数时都会复制数据,在这种情况下这没什么大不了的。但是,对于较大的结构,需要避免这种情况,因此您可以使用以下方法。

其次,您可以将点作为参考而不是按值传递。这可以通过更改 draw_line 签名以接受 Point 引用来完成,如下所示:

fn draw_line(&self, p1: &Point, p2: &Point);

但是,这意味着您现在还需要通过引用传递点,从而导致以下特征定义:

trait Engine {
    fn draw_triangle(&self, tri: Triangle) {
        self.draw_line(&tri.0, &tri.1);
        self.draw_line(&tri.1, &tri.2);
        self.draw_line(&tri.2, &tri.0);
    }

    fn draw_line(&self, p1: &Point, p2: &Point);
}

这导致 Points 本身没有被传递到函数中,而是对单个 Point 的引用——这意味着不需要复制结构六次(每个函数调用两次)。如果这个方法被调用很多,或者结构更大,这可能是一个显着的加速。

锈书的以下章节对所有权、引用和借用提供了详尽的解释:https://doc.rust-lang.org/book/ch04-00-understanding-ownership.html。

【讨论】:

    猜你喜欢
    • 2015-01-20
    • 2021-04-30
    • 2020-12-14
    • 1970-01-01
    • 2016-07-23
    • 2021-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多