rust 当从Vec和VecDeque调用`extend`和`drain`方法时,内存是如何处理的?

cqoc49vn  于 2023-10-20  发布在  其他
关注(0)|答案(2)|浏览(180)

在Rust中,来自Vec和VecDeque的方法extenddrain是复制项目的内容,还是像列表一样移动项目?
假设reserve reserve已经被调用了prior,并且Vec/VecDeque已经有了元素的空间。
编辑:为了澄清,在内存级别上,下面的代码会发生什么?内容是从Vec复制到VecDeque的,还是仅仅是指针的变化,比如在链表中删除/插入?

  1. let mut a: Vec<i32> = (0..10).collect();
  2. let mut b: VecDeque<i32> = VecDeque::new();
  3. b.reserve(10);
  4. b.extend(a.drain(..));
mctunoxg

mctunoxg1#

ab的数据位于内存中的固定位置。因为b已经有足够的容量,所以不会重新分配b
但是,数据本身将从a内存复制到b,之后a将被标记为空。
为了演示,这里有一个小程序,它显示了在这样一个过程中Vec的内部状态:

  1. use std::fmt::Debug;
  2. macro_rules! dbg_vec {
  3. ($v: ident) => {
  4. dbg_vec_impl(stringify!($v), &$v);
  5. };
  6. }
  7. fn dbg_vec_impl<T: Debug>(name: &str, v: &Vec<T>) {
  8. println!(
  9. "Vec '{}': ({:p}, {}, {})",
  10. name,
  11. v.as_ptr(),
  12. v.len(),
  13. v.capacity()
  14. );
  15. println!(" Real content: {:?}", v);
  16. unsafe {
  17. println!(
  18. " Memory content: {:?}",
  19. std::slice::from_raw_parts(v.as_ptr(), v.capacity())
  20. )
  21. };
  22. }
  23. fn main() {
  24. let mut a: Vec<i32> = (0..10).collect();
  25. let mut b: Vec<i32> = Vec::new();
  26. dbg_vec!(a);
  27. dbg_vec!(b);
  28. b.reserve(10);
  29. println!("\nb.reserve(10);\n");
  30. dbg_vec!(a);
  31. dbg_vec!(b);
  32. b.extend(a.drain(..));
  33. println!("\nb.extend(a.drain(..))\n");
  34. dbg_vec!(a);
  35. dbg_vec!(b);
  36. a.shrink_to_fit();
  37. b.shrink_to_fit();
  38. println!("\nshrink_to_fit()\n");
  39. dbg_vec!(a);
  40. dbg_vec!(b);
  41. }
  1. Vec 'a': (0x1e932d5deb0, 10, 10)
  2. Real content: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
  3. Memory content: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
  4. Vec 'b': (0x4, 0, 0)
  5. Real content: []
  6. Memory content: []
  7. b.reserve(10);
  8. Vec 'a': (0x1e932d5deb0, 10, 10)
  9. Real content: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
  10. Memory content: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
  11. Vec 'b': (0x1e932d5dd60, 0, 10)
  12. Real content: []
  13. Memory content: [5439557, 5505099, 5242959, 7667773, 6553710, 6684773, 7209065, 6553701, 5177344, 3997779]
  14. b.extend(a.drain(..))
  15. Vec 'a': (0x1e932d5deb0, 0, 10)
  16. Real content: []
  17. Memory content: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
  18. Vec 'b': (0x1e932d5dd60, 10, 10)
  19. Real content: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
  20. Memory content: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
  21. shrink_to_fit()
  22. Vec 'a': (0x4, 0, 0)
  23. Real content: []
  24. Memory content: []
  25. Vec 'b': (0x1e932d5dd60, 10, 10)
  26. Real content: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
  27. Memory content: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
展开查看全部
ykejflvf

ykejflvf2#

VecVecDeque不是链表,也不是操作链表。它们在内存中是连续的,所以是的,发生了按位复制。复制的语义可以是复制或移动,这取决于类型是否实现Copy

相关问题