问题
In C++, to copy the contents of a vector to another vector we use the assignment operator dest = src
. However, in Rust src
would be moved into dest
and no longer usable.
I know the simplest answer is to do dest = src.clone()
(for the sake of this question we'll assume T
in Vec<T>
is Clone
). However - if I'm understanding correctly - this creates a brand new third vector with the copied contents of src
and moves it into dest
, throwing away dest
's dynamically allocated array. If this is correct, it's a completely unnecessary dynamic allocation when we could have just copied the content directly into dest
(assuming it had sufficient capacity).
Below is a function I've made that does exactly what I would like to do: empty out the dest
vector and copy the elements of src
to it.
// 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());
}
}
Is there a way to do this with builtin or standard library utilities? Is the dest = src.clone()
optimized by the compiler to do this anyway?
I know that if T
has dynamic resources then the extra allocation from src.clone()
isn't a big deal, but if T
is e.g. i32
or any other Copy
type then it forces an allocation where none are necessary.
回答1:
Did you ever look at the 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()
}
}
To quote the doc:
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.
Of course a type such as Vec does not use the provided-by-default clone_from and defines its own in a more efficient way, similar to what you would get in C++ from writing dest = src
:
fn clone_from(&mut self, other: &Vec<T>) {
other.as_slice().clone_into(self);
}
with [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..]);
}
来源:https://stackoverflow.com/questions/59604714/how-can-i-copy-a-vector-to-another-location-and-reuse-the-existing-allocated-mem