存储Vec和Slice有什么区别?

25

Rust提供了几种方法来存储用户定义结构中的元素集合。结构体可以被赋予自定义生命周期指定符,并引用一个切片:

struct Foo<'a> {
    elements: &'a [i32]
}

impl<'a> Foo<'a> { 
    fn new(elements: &'a [i32]) -> Foo<'a> { 
        Foo { elements: elements }
    }
}

或者可以给它一个Vec对象:

struct Bar {
    elements: Vec<i32>
}

impl Bar {
    fn new(elements: Vec<i32>) -> Bar {
        Bar { elements: elements }
    }
}

这两种方法之间的主要区别是什么?

  • 使用 Vec 时,每次调用 Bar::new(vec![1, 2, 3, 4, 5]) 是否会强制语言复制内存?
  • Vec 的内容是否会在所有者 Bar 超出作用域时被隐式销毁?
  • 如果在传递给结构体之外的位置使用了传入的切片参数,是否存在任何危险性?
2个回答

49

Vec(向量)由三个部分组成:

  1. 指向一块内存的指针
  2. 已分配内存容量大小
  3. 存储在其内的元素数量(大小)

Slice(切片)由两个部分组成:

  1. 指向一块内存的指针
  2. 存储在其内的元素数量(大小)

当您移动这些任意一个时,上述字段都会被复制。可以看出这是非常轻量级的。实际位于堆上的内存块不会被复制或移动。

Vec表示对内存的所有权,而Slice表示对内存的借用。当一个Vec本身被释放(Rust-speak中的dropped)时,它需要释放所有的元素以及内存块。 这发生在它超出范围时。当Slice被释放时,什么也不做。

使用Slice没有任何危险,因为Rust的生命周期机制(lifetimes)会处理它们。这会确保您从未在失效后使用引用。


3
每种类型由什么组成的细分非常阐明。 - KChaloux

6
Vec是一种可以增加或缩小大小的集合。它存储在堆上,动态地在运行时分配和释放。Vec可用于存储任意数量的元素,通常在元素数量在编译时不明确或元素数量可能在程序执行期间发生变化时使用。
切片是对Vec或其他集合中连续元素序列的引用。它使用[T]语法表示,其中T是切片中元素的类型。切片本身不存储任何元素,只引用存储在另一个集合中的元素。当需要引用集合中的子集时,通常使用切片。
Vec和切片之间的主要区别之一是Vec可用于添加和删除元素,而切片仅提供对集合子集的只读访问。另一个区别是Vec存储在堆上,而切片是引用,因此具有固定大小。这意味着切片不能用于存储新元素,但可以用于引用Vec或其他集合中的元素子集。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接