避免同时借用可变和不可变
Avoiding borrowing mutable and immutable at the same time
为了添加两个 Vecs 的元素,我写了一个像这样的函数
fn add_components(dest: &mut Vec<i32>, first: &Vec<i32>, second: &Vec<i32>){
for i in 0..first.len() {
dest[i] = first[i] + second[i];
}
}
当 dest
是另一个 Vec.
时,这工作正常
let mut new_components = Vec::with_capacity(components.len());
Vector::add_components(&mut new_comps, &components, &other_components);
但是当我尝试就地添加时它爆炸了:
Vector::add_components(&mut components, &components, &other_components);
因为现在我借用 components
同时作为可变和不可变的。但这显然是我想要实现的目标。
对于这个问题,是否有任何不涉及不安全代码和指针魔术的常规和通用(意味着不仅涉及 Vecs)解决方案?
这个问题的另一个例子:
假设我想为像
这样的数字类型重载 AddAssign
impl AddAssign<Output=&NumericType> for NumericType {
fn add_assign(&mut self, other: &NumericType) {
unimplemented!() // concrete implementation is not important
}
}
请注意,我想将引用作为第二个参数以避免复制。这在添加两个不同的对象时效果很好,但将一个对象添加到自身会创建完全相同的场景:
let mut num = NumericType{};
num += &num
我正在同时以可变和不可变的方式借用 num
。所以显然这应该有效并且是安全的,但它也违反了 Rust 的借用规则。
处理这个以多种形式出现的问题的最佳做法是什么(当然除了复制之外)?
对此没有通用的解决方案。 Rust 不能在借用检查中对可变性进行一般抽象。
您需要有两个版本的函数用于就地版本和目标版本。
Rust 有严格的别名规则,所以 dest[i] = first[i] + second[i]
实际上会编译成不同的代码,这取决于编译器是否保证 dest
和 first
是不同的。不要试图用 unsafe
来捏造它,因为它将是未定义的行为并且会被错误编译。
为了添加两个 Vecs 的元素,我写了一个像这样的函数
fn add_components(dest: &mut Vec<i32>, first: &Vec<i32>, second: &Vec<i32>){
for i in 0..first.len() {
dest[i] = first[i] + second[i];
}
}
当 dest
是另一个 Vec.
let mut new_components = Vec::with_capacity(components.len());
Vector::add_components(&mut new_comps, &components, &other_components);
但是当我尝试就地添加时它爆炸了:
Vector::add_components(&mut components, &components, &other_components);
因为现在我借用 components
同时作为可变和不可变的。但这显然是我想要实现的目标。
对于这个问题,是否有任何不涉及不安全代码和指针魔术的常规和通用(意味着不仅涉及 Vecs)解决方案?
这个问题的另一个例子:
假设我想为像
这样的数字类型重载 AddAssignimpl AddAssign<Output=&NumericType> for NumericType {
fn add_assign(&mut self, other: &NumericType) {
unimplemented!() // concrete implementation is not important
}
}
请注意,我想将引用作为第二个参数以避免复制。这在添加两个不同的对象时效果很好,但将一个对象添加到自身会创建完全相同的场景:
let mut num = NumericType{};
num += &num
我正在同时以可变和不可变的方式借用 num
。所以显然这应该有效并且是安全的,但它也违反了 Rust 的借用规则。
处理这个以多种形式出现的问题的最佳做法是什么(当然除了复制之外)?
对此没有通用的解决方案。 Rust 不能在借用检查中对可变性进行一般抽象。
您需要有两个版本的函数用于就地版本和目标版本。
Rust 有严格的别名规则,所以 dest[i] = first[i] + second[i]
实际上会编译成不同的代码,这取决于编译器是否保证 dest
和 first
是不同的。不要试图用 unsafe
来捏造它,因为它将是未定义的行为并且会被错误编译。