Rust 以可变方式借用结构字段并将其传递给可变方法
因为rust不跟踪跨方法调用的单个字段借用-它假定您从整个结构中借用了字段,所以不可能从结构中借用字段,返回它,然后将其传递给其他可变方法。这听起来有点做作,但我现在有一个确切的问题Rust 以可变方式借用结构字段并将其传递给可变方法,rust,Rust,因为rust不跟踪跨方法调用的单个字段借用-它假定您从整个结构中借用了字段,所以不可能从结构中借用字段,返回它,然后将其传递给其他可变方法。这听起来有点做作,但我现在有一个确切的问题 struct Foo { x: i32, y: i32 } impl Foo { pub fn borrow_x(&mut self) -> &mut i32 { &mut sel
struct Foo {
x: i32,
y: i32
}
impl Foo {
pub fn borrow_x(&mut self) -> &mut i32 {
&mut self.x
}
pub fn cross_product(&mut self, other: &mut i32) {
self.y *= *other;
*other *= self.y;
}
}
fn main() {
let mut foo = Foo{x: 2, y: 4};
let x_ref = foo.borrow_x();
foo.cross_product(x_ref);
println!("x={} y={}", foo.x, foo.y);
}
这当然在rust中是不允许的,编译器的错误是:
error[E0499]: cannot borrow `foo` as mutable more than once at a time
--> src/main.rs:20:5
|
19 | let x_ref = foo.borrow_x();
| --- first mutable borrow occurs here
20 | foo.cross_product(x_ref);
| ^^^ ----- first borrow later used here
| |
| second mutable borrow occurs here
我的第一反应是使用“不安全”来告诉编译器它并不是真正从self借用的:
pub fn borrow_x<'a>(&mut self) -> &'a mut i32 {
unsafe {
std::mem::transmute::<&mut i32, &'a mut i32>(&mut self.x)
}
}
我认为可以将该方法全部抛弃,将对这两个字段的引用作为自由函数传递到cross_乘积中。这应该等同于上一个解决方案。但我发现这种情况很糟糕,尤其是当结构所需的字段数量增加时
这个问题还有其他解决方案吗?需要记住的是,rust是在每个功能级别工作的
pub fn cross_product(&mut self, other: &mut i32) {
self.y *= *other;
*other *= self.y;
}
可变性规则确保self.y
和other
不是一回事。
如果不小心的话,很容易在C++/C/Java中遇到这种错误
i、 想象一下,如果
let x_ref = foo.borrow_x();
foo.cross_product(x_ref);
你在干什么
let y_ref = foo.borrow_y();
foo.cross_product(y_ref);
foo.y
应该以什么值结束?(允许这些引用同一对象可能会导致某些性能优化不适用)
正如你提到的,你可以使用一个自由函数
fn cross_product(a: &mut i32, b: &mut i32) {
a *= b;
b *= a;
}
<> P>但我会考虑开沟变异性
fn cross_product(a:i32, b:i32) -> (i32,i32) {
(a*b, a*b*b)
}
旁白:如果返回值对您来说很奇怪(最初对我也是如此),并且您希望(a*b,a*b)
,那么您需要更仔细地思考一下。。。我要说的是,这本身就是避免可变版本的一个很好的理由
那我就可以这样用了
let (_x,_y) = cross_product(foo.x, foo.y);
foo.x = _x;
foo.y = _y;
这有点冗长,但当我们到达时,我们可以改为写:
(foo.y, foo.x) = cross_product(foo.x, foo.y);
需要记住的是,rust在每个功能级别都起作用
pub fn cross_product(&mut self, other: &mut i32) {
self.y *= *other;
*other *= self.y;
}
可变性规则确保self.y
和other
不是一回事。
如果不小心的话,很容易在C++/C/Java中遇到这种错误
i、 想象一下,如果
let x_ref = foo.borrow_x();
foo.cross_product(x_ref);
你在干什么
let y_ref = foo.borrow_y();
foo.cross_product(y_ref);
foo.y
应该以什么值结束?(允许这些引用同一对象可能会导致某些性能优化不适用)
正如你提到的,你可以使用一个自由函数
fn cross_product(a: &mut i32, b: &mut i32) {
a *= b;
b *= a;
}
<> P>但我会考虑开沟变异性
fn cross_product(a:i32, b:i32) -> (i32,i32) {
(a*b, a*b*b)
}
旁白:如果返回值对您来说很奇怪(最初对我也是如此),并且您希望(a*b,a*b)
,那么您需要更仔细地思考一下。。。我要说的是,这本身就是避免可变版本的一个很好的理由
那我就可以这样用了
let (_x,_y) = cross_product(foo.x, foo.y);
foo.x = _x;
foo.y = _y;
这有点冗长,但当我们到达时,我们可以改为写:
(foo.y, foo.x) = cross_product(foo.x, foo.y);