ChatGPT解决这个技术问题 Extra ChatGPT

Is it more efficient to copy a vector by reserving and copying, or by creating and swapping? [duplicate]

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.

Second one has misleading name - as it is not a copy (although it is fast).

g
gsamaras

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.


In fact the approach is passing by value, the compiler calls the copy constructor, and then swapping that newly created element. That is why rlbond suggests calling the copy constructor directly to achieve the same effect.
However, you can't call rlbon without a function that passes the original as val. Otherwise, the original one will be empties. The second solution made sure that you will always call by value and hence you will not lose the date in the original vector. (Assuming swap deals with pointers)
Won't that move the elements of b to a (leaving b with size == 0)?
@Jonathan. Assuming you're talking about a = b then no. Assignment means: make a equal b without changing b. By contrast, std::swap(a, b) would exchange their contents (so b's size would now be whatever a'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 leave b in an, ahem, "interesting" state - see stackoverflow.com/questions/17730689/…
@Jonathan. Note the double ampersand &&. That version will only be used for an rvalue reference. It won't match any non-const value (such as b in my example above). You can turn b into one by saying a = std::move(b); See en.cppreference.com/w/cpp/language/value_category for even greater levels of complexity.
r
rlbond

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);

Good, it works. But it's not working for an array of vectors: for e.g: vector A[n];
That is swap, not copy.
@sdd - no it's not. Check the argument list. original is a copy of the function argument.
@rlbond Accidentally downvoted the answer :(, Can you please edit the post, so that i can remove the downvote and give the upvote?
p
phoenix

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.


More flexible for me is a = b; because I already have member field a and I just need to assign it with the new value from b
J
Jerry Yang

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


F
Farid Chowdhury
new_vector.assign(old_vector.begin(),old_vector.end()); // Method 1
new_vector = old_vector; // Method 2

R
Raz

you should not use swap to copy vectors, it would change the "original" vector.

pass the original as a parameter to the new instead.