This question already has answers here: Copying std::vector: prefer assignment or std::copy? (6 answers) Closed 1 year ago.
I am trying to efficiently make a copy of a vector. I see two possible approaches:
std::vector<int> copyVecFast1(const std::vector<int>& original)
{
std::vector<int> newVec;
newVec.reserve(original.size());
std::copy(original.begin(), original.end(), std::back_inserter(newVec));
return newVec;
}
std::vector<int> copyVecFast2(std::vector<int>& original)
{
std::vector<int> newVec;
newVec.swap(original);
return newVec;
}
Which of these is preferred, and why? I am looking for the most efficient solution that will avoid unnecessary copying.
They aren't the same though, are they? One is a copy, the other is a swap. Hence the function names.
My favourite is:
a = b;
Where a
and b
are vectors.
Your second example does not work if you send the argument by reference. Did you mean
void copyVecFast(vec<int> original) // no reference
{
vector<int> new_;
new_.swap(original);
}
That would work, but an easier way is
vector<int> new_(original);
original
is a copy of the function argument.
This is another valid way to make a copy of a vector, just use its constructor:
std::vector<int> newvector(oldvector);
This is even simpler than using std::copy
to walk the entire vector from start to finish to std::back_insert
them into the new vector.
That being said, your .swap()
one is not a copy, instead it swaps the two vectors. You would modify the original to not contain anything anymore! Which is not a copy.
a = b;
because I already have member field a
and I just need to assign it with the new value from b
Direct answer:
Use a = operator
We can use the public member function std::vector::operator=
of the container std::vector
for assigning values from a vector to another.
Use a constructor function
Besides, a constructor function also makes sense. A constructor function with another vector as parameter(e.g. x
) constructs a container with a copy of each of the elements in x
, in the same order.
Caution:
Do not use std::vector::swap
std::vector::swap
is not copying a vector to another, it is actually swapping elements of two vectors, just as its name suggests. In other words, the source vector to copy from is modified after std::vector::swap
is called, which is probably not what you are expected.
Deep or shallow copy?
If the elements in the source vector are pointers to other data, then a deep copy is wanted sometimes.
According to wikipedia:
A deep copy, meaning that fields are dereferenced: rather than references to objects being copied, new copy objects are created for any referenced objects, and references to these placed in B.
Actually, there is no currently a built-in way in C++ to do a deep copy. All of the ways mentioned above are shallow. If a deep copy is necessary, you can traverse a vector and make copy of the references manually. Alternatively, an iterator can be considered for traversing. Discussion on iterator is beyond this question.
References
The page of std::vector
on cplusplus.com
new_vector.assign(old_vector.begin(),old_vector.end()); // Method 1
new_vector = old_vector; // Method 2
you should not use swap to copy vectors, it would change the "original" vector.
pass the original as a parameter to the new instead.
Success story sharing
a = b
then no. Assignment means: makea
equalb
without changingb
. By contrast,std::swap(a, b)
would exchange their contents (sob
'ssize
would now be whatevera
's had been before). You are perhaps thinking of a move operation (as occurs in C++11, but not in an ordinary assignment like this). Such a move would leaveb
in an, ahem, "interesting" state - see stackoverflow.com/questions/17730689/…&&
. That version will only be used for an rvalue reference. It won't match any non-const value (such asb
in my example above). You can turnb
into one by sayinga = std::move(b);
See en.cppreference.com/w/cpp/language/value_category for even greater levels of complexity.