【问题标题】:Swapping vectors [closed]交换向量
【发布时间】:2021-09-21 15:43:43
【问题描述】:

我需要将一个向量的值分配给另一个向量,例如:

let mut vec_a: Vec<f64> = vec![0.1; 100];
let mut vec_b: Vec<f64> = vec![0.1; 100];

// Do something with vec_a. Real vectors are ~1e6 long    
unsafe {
    vec_b = Vec::from_raw_parts(&vec_a, vec_a.len(), vec_a.len());
}

我正在寻求帮助来回答这些问题:

有没有更有效、更安全的方法?

如果所有内容都由同一个应用程序/代码处理,为什么它必须在 unsafe 代码下?

如果是正确的方式,用Vec::from_raw_parts代替std::slice::from_raw_parts会不会有区别?

这种需求背后的原因是为了避免复制数据。这可能会以很高的频率发生,并且每次,一个向量将成为跟踪最佳解决方案的存储(比如说vec_a),另一个将探索其他解决方案。当找到更好的解决方案时,唯一需要更改的是将pointer 更改为向量,现在vec_a 存储在vec_bvec_b 中找到的最佳解决方案,并且vec_b 可以继续探索不同的解决方案。

【问题讨论】:

  • 为什么需要将一个向量的值赋值给另一个向量?你不能使用切片引用来代替吗?或者可能引用向量?
  • 您的要求与vec_b = vec_a.clone(); 有何不同?您似乎试图避免复制,但如果没有复制,为什么有两个向量? (您所写的内容无法编译,因此不太清楚您期望 unsafe 块做什么。)
  • 也许只是vec_b = vec_a;?或者直接回答标题,有std::mem::swap(&amp;mut vec_a, &amp;mut vec_b)?这些都不会复制数据
  • 请注意,您当前的代码是安全的,因为您将有两个向量指向相同的数据。

标签: arrays vector rust copy


【解决方案1】:

天真的答案相当有效。简单的赋值 (best_solution = solution) 不会对元素进行深层复制,它只会转移所有权并销毁源。

let mut best_solution = vec![0.1; 100];
loop {
    let solution = generate_solution();
    if solution > best_solution {
        best_solution = solution;
    }
}

为了提高性能,您可以做的一件事是通过使用持久性 vec 作为暂存空间来减少分配(您可能在帖子中的代码中得到了这一点)。在这种情况下,您将使用std::mem::swap 来避免破坏临时向量。

let mut best_solution = vec![0.1; 100];
let mut scratch_solution = vec![0.1; 100];
loop {
    generate_solution(&mut scratch_solution);
    if scratch_solution > best_solution {
        std::mem::swap(&mut best_solution, &mut scratch_solution);
    }
}

【讨论】:

    【解决方案2】:

    您应该为此只使用交换和移动。 检查这个表明交换向量只改变指针的测试:

    fn main() {
        let mut v1 = vec![0; 100];
        let mut v2 = vec![0; 100];
        let old_ptr1 = v1.as_ptr();
        let old_ptr2 = v2.as_ptr();
        std::mem::swap(&mut v1, &mut v2);
        assert_eq!(old_ptr1, v2.as_ptr());
        assert_eq!(old_ptr2, v1.as_ptr());
    }
    

    【讨论】:

      【解决方案3】:

      很难说出你的意图,但是如果你想将源向量的所有值移动到目标向量而不丢失目标的内容,那么你可以交换向量的内容而不复制数据。例如

      fn main() {
          let mut vec_a: Vec<f64> = vec![0.1; 100];
          let mut vec_b: Vec<f64> = vec![0.2; 100];
          println!("{}", vec_a[0]); // 0.1
          println!("{}", vec_b[0]); // 0.2
          
          let (mut vec_a, mut vec_b) = (vec_b, vec_a);
          println!("{}", vec_a[0]); // 0.2
          println!("{}", vec_b[0]); // 0.1
      }
      

      【讨论】:

      • 这将旧变量vec_avec_b 与具有相同名称的新变量遮蔽,只是交换了。我想不出这会在什么情况下有用。
      猜你喜欢
      • 1970-01-01
      • 2016-09-19
      • 1970-01-01
      • 2011-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-15
      • 1970-01-01
      相关资源
      最近更新 更多