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

问题描述 投票:0回答:2

在 Rust 中,Vec 和 VecDeque 中的方法

extend
drain
是复制项目的内容,还是像列表一样移动项目?

考虑到

reserve
预留已被提前调用,并且 Vec/VecDeque 已经有用于元素的空间。

编辑:为了澄清,下面的代码在内存级别会发生什么?内容是从 Vec 复制到 VecDeque,还是只是指针发生了变化,例如在链表中删除/插入?

let mut a: Vec<i32> = (0..10).collect();
let mut b: VecDeque<i32> = VecDeque::new();
b.reserve(10);

b.extend(a.drain(..));
rust vector memory-management vec-deque
2个回答
1
投票

a
b
的数据位于内存中的固定位置。因为
b
已经有足够的容量,所以不会发生
b
的重新分配。

数据本身将从

a
内存复制到
b
,并且
a
之后将被标记为空。


为了演示,这里有一个小程序,显示了

Vec
在这个过程中的内部状态:

use std::fmt::Debug;

macro_rules! dbg_vec {
    ($v: ident) => {
        dbg_vec_impl(stringify!($v), &$v);
    };
}

fn dbg_vec_impl<T: Debug>(name: &str, v: &Vec<T>) {
    println!(
        "Vec '{}': ({:p}, {}, {})",
        name,
        v.as_ptr(),
        v.len(),
        v.capacity()
    );
    println!("    Real content:   {:?}", v);
    unsafe {
        println!(
            "    Memory content: {:?}",
            std::slice::from_raw_parts(v.as_ptr(), v.capacity())
        )
    };
}

fn main() {
    let mut a: Vec<i32> = (0..10).collect();
    let mut b: Vec<i32> = Vec::new();
    dbg_vec!(a);
    dbg_vec!(b);

    b.reserve(10);
    println!("\nb.reserve(10);\n");

    dbg_vec!(a);
    dbg_vec!(b);

    b.extend(a.drain(..));
    println!("\nb.extend(a.drain(..))\n");

    dbg_vec!(a);
    dbg_vec!(b);

    a.shrink_to_fit();
    b.shrink_to_fit();
    println!("\nshrink_to_fit()\n");

    dbg_vec!(a);
    dbg_vec!(b);
}
Vec 'a': (0x1e932d5deb0, 10, 10)
    Real content:   [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    Memory content: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Vec 'b': (0x4, 0, 0)
    Real content:   []
    Memory content: []

b.reserve(10);

Vec 'a': (0x1e932d5deb0, 10, 10)
    Real content:   [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    Memory content: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Vec 'b': (0x1e932d5dd60, 0, 10)
    Real content:   []
    Memory content: [5439557, 5505099, 5242959, 7667773, 6553710, 6684773, 7209065, 6553701, 5177344, 3997779]

b.extend(a.drain(..))

Vec 'a': (0x1e932d5deb0, 0, 10)
    Real content:   []
    Memory content: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Vec 'b': (0x1e932d5dd60, 10, 10)
    Real content:   [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    Memory content: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

shrink_to_fit()

Vec 'a': (0x4, 0, 0)
    Real content:   []
    Memory content: []
Vec 'b': (0x1e932d5dd60, 10, 10)
    Real content:   [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    Memory content: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

1
投票

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

© www.soinside.com 2019 - 2024. All rights reserved.