我是Rust编程语言的新手,我只是在玩它。我读到了Rust借用的东西,我想我理解为什么编译器不接受以下代码,但我不知道如何正确使用它:
struct Pixel;
struct Canvas {
pixel : Pixel,
}
impl Canvas {
fn drawPixel(&mut self, y : usize, x : usize, pixel : &Pixel) {
// Modify internal pixmap using given Pixel description.
}
fn setPixel(&mut self, y : usize, x : usize) {
// Draw a pixel to internal pixmap using own pixel description.
self.drawPixel(y, x, &self.pixel);
}
}
这是编译器报告的错误:
src/main.rs:14:35: 14:45 error: cannot borrow `self.pixel` as immutable because `*self` is also borrowed as mutable
src/main.rs:14 self.drawPixel(y, x, &self.pixel);
^~~~~~~~~~
src/main.rs:14:13: 14:17 note: previous borrow of `*self` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `*self` until the borrow ends
src/main.rs:14 self.drawPixel(y, x, &self.pixel);
^~~~
src/main.rs:14:46: 14:46 note: previous borrow ends here
src/main.rs:14 self.drawPixel(y, x, &self.pixel);
这个例子中的想法是有一个方法' drawPixel'可以根据指定的“像素”绘制像素。第二种方法' setPixel'只是转发到前一种方法,通过它来引用“像素”'与“画布”相关的实例'对象
请不要问我为什么要这样做。它是我真实用例的简化版本。而且我真的想知道如何编译这段代码。
答案 0 :(得分:3)
根本问题是drawPixel
中对setPixel
的调用会为drawPixel
字段提供pixel
两个别名:可变的self
字段(如self.pixel
},以及pixel
参数中的不可变参数。在Rust中,非mut
指针确实是指向不可变值的指针。但是,使用这两个别名,drawPixel
将能够改变pixel
参数引用的像素值,并且其值将意外更改。
如果Pixel
是小型(例如,RGBA四元组)并且未实现Drop
,则可以将其设为Copy
,然后只传递Pixel
按值(见A.B.'s answer)。
如果那是不可能的,那么考虑drawPixel
实际需要变异的内容。是否需要改变pixel
字段?如果是,您需要以某种方式复制像素,否则当您改变字段时pixel
参数的值将会改变,如上所述。在这种情况下,您可能只能实现Clone
并使用clone()
方法获取像素的副本。
如果您不需要改变pixel
中的drawPixel
字段,那么您可以在单独的结构中移动您变异的字段,并将drawPixel
方法移动到该字段结构改为。这样,&mut self
将应用于内部结构,它肯定不会与pixel
字段别名。
struct Pixel;
struct Canvas2;
struct Canvas {
canvas2 : Canvas2,
pixel : Pixel,
}
impl Canvas2 {
fn drawPixel(&mut self, y : usize, x : usize, pixel : &Pixel) {
// Modify internal pixmap using given Pixel description.
}
}
impl Canvas {
fn setPixel(&mut self, y : usize, x : usize) {
// Draw a pixel to internal pixmap using own pixel description.
self.canvas2.drawPixel(y, x, &self.pixel);
}
}
答案 1 :(得分:2)
如何正确使用取决于您需要什么以及Pixel在实际代码中的实际外观。
由于Pixel可能是一个可以轻易复制的轻量级对象,因此您可以按值传递它。
#[derive(Copy, Clone)]
struct Pixel;
struct Canvas {
pixel : Pixel,
}
impl Canvas {
fn drawPixel(&mut self, y : usize, x : usize, pixel : Pixel) {
// Modify internal pixmap using given Pixel description.
}
fn setPixel(&mut self, y : usize, x : usize) {
// Draw a pixel to internal pixmap using own pixel description.
self.drawPixel(y, x, self.pixel);
}
}