Why is the copy-ctor preferred over move-ctor when std::vector relocates storage?

Viewed 93

I am learning the behavior of std::vector: how it relocates (copies/moves) objects when reserving more capacity:

#include<vector>
#include<iostream>
using namespace std;

struct A{
   A(const A& a){ i=a.i; cerr<<"copied "<<i<<endl; }  //(1)
   A(     A&& a){ i=a.i; cerr<<"moved "<<i<<endl; }
   A(int i):i(i){cerr<<"created "<<i<<endl;};
   A(){};
private:
   int i=0;
};
int main()
{
   vector<A> v1;
   size_t prevcap=v1.capacity();
   for(int i=0; i<10; ++i){
      v1.emplace_back(i);
      if(prevcap!=v1.capacity()){
         cerr<<"capacity increased to "<<v1.capacity()<<endl;
         prevcap=v1.capacity();
      }
      cerr<<"------"<<endl;
   }
}

With my g++-10 the output is:

created 0
capacity increased to 1
------
created 1
copied 0
capacity increased to 2
------
created 2
copied 0
copied 1
capacity increased to 4
------
created 3
------
created 4
copied 0
copied 1
copied 2
copied 3
capacity increased to 8
------
created 5
------
created 6
------
created 7
------
created 8
copied 0
copied 1
copied 2
copied 3
copied 4
copied 5
copied 6
copied 7
capacity increased to 16
------
created 9
------

If remove copy-construtor (1) the output would be:

created 0
capacity increased to 1
------
created 1
moved 0
capacity increased to 2
------
created 2
moved 0
moved 1
capacity increased to 4
------
created 3
------
created 4
moved 0
moved 1
moved 2
moved 3
capacity increased to 8
------
created 5
------
created 6
------
created 7
------
created 8
moved 0
moved 1
moved 2
moved 3
moved 4
moved 5
moved 6
moved 7
capacity increased to 16
------
created 9
------

Why if both copy and move ctors exist is the copy-ctor preferred?


Update. Thx to @Jarod42. Add noexcept

struct A{
   A(const A& a)noexcept{ i=a.i; cerr<<"copied "<<i<<endl; }
   A(     A&& a)noexcept{ i=a.i; cerr<<"moved "<<i<<endl; }
   A(int i)noexcept:i(i){cerr<<"created "<<i<<endl;};
   A()noexcept{};
private:
   int i=0;
};

output:

created 0
capacity increased to 1
------
created 1
moved 0
capacity increased to 2
------
created 2
moved 0
moved 1
capacity increased to 4
------
created 3
------
created 4
moved 0
moved 1
moved 2
moved 3
capacity increased to 8
------
created 5
------
created 6
------
created 7
------
created 8
moved 0
moved 1
moved 2
moved 3
moved 4
moved 5
moved 6
moved 7
capacity increased to 16
------
created 9
------

Now moved. But what is the logic behind this?

0 Answers
Related