如何将向量复制到另一个位置并重用现有的分配内存?

Cru*_*ean 7 clone copy vector rust

在 C++ 中,要将向量的内容复制到另一个向量,我们使用赋值运算符dest = src。但是,在 Rustsrc中将被移入dest并且不再可用。

我知道最简单的答案是做dest = src.clone()(对于这个问题,我们会承担的缘故TVec<T>Clone)。但是 - 如果我理解正确的话 - 这会创建一个全新的第三向量,其中复制了 的内容src并将其移动到 中dest,丢弃了dest动态分配的数组。如果这是正确的,当我们可以直接将内容复制到dest(假设它有足够的容量)时,这是完全不必要的动态分配。

下面是我制作的一个函数,它完全符合我的意愿:清空dest向量并将 的元素复制src到其中。

// copy contents of src to dest without just cloning src
fn copy_content<T: Clone>(dest: &mut Vec<T>, src: &Vec<T>) {
    dest.clear();
    if dest.capacity() < src.len() {
        dest.reserve(src.len());
    }
    for x in src {
        dest.push(x.clone());
    }
}
Run Code Online (Sandbox Code Playgroud)

有没有办法使用内置或标准库实用程序来做到这一点?dest = src.clone()编译器是否优化过这样做?

我知道如果T有动态资源,那么额外的分配src.clone()就没什么大不了的,但是如果T是 egi32或任何其他Copy类型,那么它会强制分配不需要的资源。

mca*_*ton 11

你有没有看过的定义Clone?它有众所周知的clone方法,但也有一个有用但经常被遗忘的clone_from方法

pub trait Clone : Sized {
    fn clone(&self) -> Self;
    fn clone_from(&mut self, source: &Self) {
        *self = source.clone()
    }
}
Run Code Online (Sandbox Code Playgroud)

引用文档:

从源执行复制分配。

a.clone_from(&b)等效于a = b.clone()in 功能,但可以重写以重用 的资源a以避免不必要的分配。

当然,诸如此类的类型Vec不使用默认提供的类型,而是clone_from以更有效的方式定义自己的类型,类似于您在 C++ 中编写的内容dest = src

fn clone_from(&mut self, other: &Vec<T>) {
    other.as_slice().clone_into(self);
}
Run Code Online (Sandbox Code Playgroud)

[T]::clone_into被定义为

fn clone_into(&self, target: &mut Vec<T>) {
    // drop anything in target that will not be overwritten
    target.truncate(self.len());
    let len = target.len();

    // reuse the contained values' allocations/resources.
    target.clone_from_slice(&self[..len]);

    // target.len <= self.len due to the truncate above, so the
    // slice here is always in-bounds.
    target.extend_from_slice(&self[len..]);
}
Run Code Online (Sandbox Code Playgroud)