Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/batch-file/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Methods 如何在Rust中使用对象作为其自身方法的参数?_Methods_Rust_Borrow Checker_Mutability - Fatal编程技术网

Methods 如何在Rust中使用对象作为其自身方法的参数?

Methods 如何在Rust中使用对象作为其自身方法的参数?,methods,rust,borrow-checker,mutability,Methods,Rust,Borrow Checker,Mutability,我为Rust中的一个简单结构编写了以下代码。这只是一个例子,它没有太多真正的逻辑: struct Vec2 { x: f32, y: f32, } impl Vec2 { fn multiply(&mut self, other: &Vec2) { self.x *= other.x; self.y *= other.y; } } 我可以创建简单的向量并将一个向量与另一个向量相乘,但当我尝试将一个向量与自身相乘时

我为Rust中的一个简单结构编写了以下代码。这只是一个例子,它没有太多真正的逻辑:

struct Vec2 {
    x: f32,
    y: f32,
}

impl Vec2 {
    fn multiply(&mut self, other: &Vec2) {
        self.x *= other.x;
        self.y *= other.y;
    }
}
我可以创建简单的向量并将一个向量与另一个向量相乘,但当我尝试将一个向量与自身相乘时遇到了一个问题:编译器抱怨我不能将该向量作为可变向量借用,因为它也是作为不可变向量借用的

fn main() {
    let mut vec = Vec2 { x: 2.0, y: 2.3 };
    vec.multiply(&vec);
}
error[E0502]:无法将'vec'作为可变项借用,因为它也是作为不可变项借用的
-->src/main.rs:15:5
|
15 |向量乘(&vec);
|     ^^^^--------^----^
|     |   |        |
|| |此处发生不可变借用
||不可变借阅稍后由调用使用
|可变借用发生在这里

这是有道理的,但将这样一个向量与其自身相乘的正确方法是什么?更重要的是:在一般情况下,我需要用自己的方法修改一个结构,并使用相同的结构作为参数。

我想你已经理解了这一点,但你现在所做的不起作用的原因是一个值不能与一个不可变的借来同时可变地借来。要按原样执行该方法,您需要同时使用可变借用(以
和mut self
的形式)和不可变借用(以
其他:&Vec2
的形式)。由于您的方法应该适用于
Vec2
的任意两个成员,因此您将始终有两个单独的借用:编译器无法推断单个借用适用于向量自身相乘的情况

至于你的问题,你有几个选择,这取决于你想做什么的细节

备选案文1:克隆 只需将
#[派生(克隆)]
添加到
Vec2
的定义中,就可以使用
Clone
方法克隆该类型的元素

#[derive(Clone)]
struct Vec2 {
    x: f32,
    y: f32,
}

impl Vec2 {
    fn multiply(&mut self, other: &Vec2) {
        self.x *= other.x;
        self.y *= other.y;
    }
}

fn main() {
    let mut vec = Vec2 { x: 2.0, y: 2.3 };
    vec.multiply(&vec.clone());
}
备选案文2:复制 如果您的类型如此简单(只有两个浮点数),那么您也可以合理地派生
Copy
。然后,该类型的元素在馈送到函数时被简单地复制,而不需要引用。这意味着我们应该更改
Vec2::multiply
的签名,将
other
简单地看作
Vec2
,而不是
&Vec2
(这并不是严格必要的,但对于
复制类型,使用指针通常效率较低)

备选方案3:专用方法 您可以有一个单独的方法,名为
multiply\u self
square
(取决于您的语义),它只需要
&mut self
。在使用自身修改结构的一般情况下,这可能是最好的选择

struct Vec2 {
    x: f32,
    y: f32,
}

impl Vec2 {
    fn multiply_self(&mut self) {
        self.x *= self.x;
        self.y *= self.y;
    }
}

fn main() {
    let mut vec = Vec2 { x: 2.0, y: 2.3 };
    vec.multiply_self();
}
选项4:返回一个新值 您可以有一个方法,该方法不可变地接受
self
,而是返回一个新的
Vec2
。然后你可以做
vec=vec.multiply(&vec)


可能还有很多其他方法可以做到这一点,但这就是在这个简单的例子中想到的。如果您能分享更多关于您尝试做什么的详细信息,我可能会想出更多。

在这种特殊情况下,最简单的解决方案是为
Vec2
导出
Copy
,并通过值而不是引用来接受
其他
struct Vec2 {
    x: f32,
    y: f32,
}

impl Vec2 {
    fn multiply_self(&mut self) {
        self.x *= self.x;
        self.y *= self.y;
    }
}

fn main() {
    let mut vec = Vec2 { x: 2.0, y: 2.3 };
    vec.multiply_self();
}
struct Vec2 {
    x: f32,
    y: f32,
}

impl Vec2 {
    fn multiply(&self, other: &Vec2) -> Vec2 {
        Vec2 {
            x: self.x * other.x,
            y: self.y * other.y,
        }
    }
}

fn main() {
    let mut vec = Vec2 { x: 2.0, y: 2.3 };
    vec = vec.multiply(&vec)
}