我为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]: cannot borrow `vec` as mutable because it is also borrowed as immutable
--> src/main.rs:15:5
|
15 | vec.multiply(&vec);
| ^^^^--------^----^
| | | |
| | | immutable borrow occurs here
| | immutable borrow later used by call
| mutable borrow occurs here
这是有道理的,但是将这样的向量与自身相乘的正确方法是什么?更重要的是:对于一般情况,我需要使用自己的方法(使用与参数相同的结构)来修改结构。
答案 0 :(得分:6)
我认为您已经了解了这一点,但是现在拥有的东西不起作用的原因是,不能将价值与可变借贷同时可变地借入。要按原样执行该方法,您需要同时使用可变借用(&mut self
形式和不可变借用(other: &Vec2
形式) 。由于您的方法应适用于Vec2
的任意两个成员,因此始终会有两个单独的借用项:编译器无法推断出将向量自身相乘的情况,单次借用将起作用。
对于您的问题,您有几种选择,具体取决于您要执行的操作。
只需将#[derive(Clone)]
添加到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());
}
如果您的类型很简单(只有两个浮点数),则可以合理地派生Copy
。然后,将类型的元素简单地复制到函数中,而不需要引用。这意味着我们应该更改Vec2::multiply
的签名,以简单地将other
代替Vec2
来使用&Vec2
(这不是严格必要的,但通常使用指针是Copy
类型的效率较低)。
#[derive(Copy, 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);
}
您可能有一个名为multiply_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();
}
您可能拥有一种方法,该方法不会可变地使用self
,而是返回一个新的Vec2
。然后,您可以做vec = vec.multiply(&vec)
。
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)
}
可能还有许多其他方法可以做到这一点,但这就是这种简单情况。如果您分享有关您总体上打算做什么的更多细节,我也许可以提出更多建议。