Why does std :: vector :: insert need to copy the destination?

I tried to understand the following behavior:

#include <vector> #include <iterator> struct Foo { Foo(int a) : a_ {a} {} const int a_; // Note the const }; int main(int argc, char **argv) { std::vector<Foo> v1 {Foo {0}}; std::vector<Foo> v2 {Foo {1}}; auto first = std::begin(v2); auto last = std::end(v2); for (; first != last; ++first) { v1.push_back(*first); // Fine } //v1.insert(v1.begin(), first, last); // Does not compile return 0; } 

It turns out that the const Foo member implicitly deletes the Foo copy-assign statement, which is used by std::vector::insert .

Why does std::vector::insert need to copy the destination when std::vector::push_back copies? Does this mean that it can be more efficient to manually concatenate two vectors? It uses LLVM.

+5
c ++ vector c ++ 11
source share
2 answers

There is no reason why an assignment operator is required, logically speaking. The insert operation can be fully implemented by moving any existing element vec[x] to vec[x+1] using (approximately) vec[x+1].~T(); new(&vec[x+1]) T(std::move(vec[x])); vec[x+1].~T(); new(&vec[x+1]) T(std::move(vec[x])); in a loop to destroy an existing element and use the inline structure to move the previous element forward.

However, a more natural approach to writing this, which in well-designed classes is usually no less effective, if not more so, is to use the purpose for this: vec[x+1] = std::move(vec[x]); . An easy example of when it can be more efficient is that constructing and destroying vector elements are related to allocating and freeing memory: using assignments easily circumvents this.

It was decided that using vectors to use assignment operators has more advantages than disadvantages. Your class is unusual and your class does not use this solution. This is sad, but there is no way to design a vector that is ideal for each use case.

+6
source share

To insert an element into the vector, if this is not the end, you must move all the elements of the tail

 [1][2][3][4][5] | | | \ \ [1][2][3][6][4][5] 

therefore, a move or copy constructor is required.

http://en.cppreference.com/w/cpp/container/vector/insert

You can still convert the loop to

 copy(first, last, back_insterter(v1)) 
+2
source share

All Articles