Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.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
Rust 避免同时借用可变和不可变_Rust_Borrowing - Fatal编程技术网

Rust 避免同时借用可变和不可变

Rust 避免同时借用可变和不可变,rust,borrowing,Rust,Borrowing,为了添加两个向量的元素,我编写了如下函数 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]; } } 但当我试图添加以下内容时,它会爆炸: Vector::add_components(&mut

为了添加两个向量的元素,我编写了如下函数

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];
  }
}
但当我试图添加以下内容时,它会爆炸:

Vector::add_components(&mut components, &components, &other_components);
因为现在我借用了
组件
作为可变和不可变的组件。但这显然是我想要实现的

对于这个问题,是否有任何常规的和通用的(不仅仅是关于VEC的)解决方案不涉及不安全的代码和指针魔法

这个问题的另一个例子:

假设我想重载AddAssign,以获得一个数字类型,如

impl AddAssign<Output=&NumericType> for NumericType {
  fn add_assign(&mut self, other: &NumericType) {
    unimplemented!() // concrete implementation is not important
  }
}
我同时可变和不变地借用
num
。所以很明显,这应该是可行的,也是安全的,但这也违反了Rust的借款规则


处理这个问题的最佳实践(当然除了复制)是什么?这个问题有很多种形式?

没有通用的解决方案。在借阅检查中,锈一般不能抽象出过度的易变性

对于就地版本和目标版本,您需要有两个版本的函数


Rust有严格的别名规则,因此
dest[i]=first[i]+second[i]
实际上编译成不同的代码,这取决于编译器是否保证
dest
first
是不同的。不要试图用
不安全的
来捏造它,因为它将是未定义的行为,并且将被错误地编译。

函数参数列表中的双逗号只是一个输入错误,还是您实际上是在用双逗号编译代码?@Bobulous,它们是输入错误!如果“扩展”不是您想要的,那么我就无法确定您的目标,即使您添加了其他示例。避免复制的唯一方法是获取源的所有权,或者使用引用(而使用引用涉及复制)。也许其他人可以提供建议,但这让我摸不着头脑。@Bobulus在我的第一个示例中,我显然在尝试替换Vec的元素,而Vec的
extend
根本没有。但这也与我的问题无关:当一个函数将同一个对象作为可变和不可变参数时,我能做什么?当答案是没有规范化的解决方法或者它包含指针时,那就没问题了。错了吗?在这种情况下,这到底意味着什么?我的例子怎么会导致产生错误结果甚至崩溃的机器代码呢?UB意味着编译器可以做任何它想做的事情,包括鼻魔,UB是不可协商的。“但在我的情况下,它实际上并不重要!”在实践中,严格的别名允许编译器假设哪个内存不会改变,并按照它认为合适的方式重新排序读写。在非平凡的情况下,这可能会导致不同的结果。如果您运气不好,优化器可能会看到您在严格别名上“作弊”,根据定义推断它是UB,并且具有UB的代码不可能存在,因此它会删除代码。
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