如何将向量复制到另一个位置并重用现有分配的内存?
How can I copy a vector to another location and reuse the existing allocated memory?
在 C++ 中,要将一个向量的内容复制到另一个向量,我们使用赋值运算符 dest = src
。然而,在 Rust 中,src
将被移动到 dest
并且不再可用。
我知道最简单的答案是 dest = src.clone()
(为了这个问题,我们假设 Vec<T>
中的 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());
}
}
有没有办法使用内置或标准库实用程序来做到这一点? dest = src.clone()
是否由编译器优化以执行此操作?
我知道如果 T
有动态资源那么来自 src.clone()
的额外分配不是什么大问题,但是如果 T
是例如i32
或任何其他 Copy
类型,然后它会在需要 none 的地方强制分配。
你有没有看过 definition of Clone
? It has the well known clone
method but also a useful but often forgotten clone_from
method:
pub trait Clone : Sized {
fn clone(&self) -> Self;
fn clone_from(&mut self, source: &Self) {
*self = source.clone()
}
}
引用文档:
Performs copy-assignment from source.
a.clone_from(&b)
is equivalent to a = b.clone()
in functionality, but can be overridden to reuse the resources of a
to avoid unnecessary allocations.
当然 a type such as Vec
does not use the provided-by-default clone_from
and defines 它自己以一种更有效的方式,类似于您在 C++ 中通过编写 dest = src
:
获得的结果
fn clone_from(&mut self, other: &Vec<T>) {
other.as_slice().clone_into(self);
}
与 [T]::clone_into
being defined as:
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..]);
}
在 C++ 中,要将一个向量的内容复制到另一个向量,我们使用赋值运算符 dest = src
。然而,在 Rust 中,src
将被移动到 dest
并且不再可用。
我知道最简单的答案是 dest = src.clone()
(为了这个问题,我们假设 Vec<T>
中的 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());
}
}
有没有办法使用内置或标准库实用程序来做到这一点? dest = src.clone()
是否由编译器优化以执行此操作?
我知道如果 T
有动态资源那么来自 src.clone()
的额外分配不是什么大问题,但是如果 T
是例如i32
或任何其他 Copy
类型,然后它会在需要 none 的地方强制分配。
你有没有看过 definition of Clone
? It has the well known clone
method but also a useful but often forgotten clone_from
method:
pub trait Clone : Sized {
fn clone(&self) -> Self;
fn clone_from(&mut self, source: &Self) {
*self = source.clone()
}
}
引用文档:
Performs copy-assignment from source.
a.clone_from(&b)
is equivalent toa = b.clone()
in functionality, but can be overridden to reuse the resources ofa
to avoid unnecessary allocations.
当然 a type such as Vec
does not use the provided-by-default clone_from
and defines 它自己以一种更有效的方式,类似于您在 C++ 中通过编写 dest = src
:
fn clone_from(&mut self, other: &Vec<T>) {
other.as_slice().clone_into(self);
}
与 [T]::clone_into
being defined as:
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..]);
}