title: does std::vector copy/move elements when re-sizing?
body: <p>I was messing around with move c'tors for a learning / refresh exercise and I came across something unexpected to me. Below I have a class <code>person</code> that contains a <code>std::string m_name;</code>. I am using this as a test class for copy/move c'tors.</p>
  <p>Here is the code for quick reference:</p>
  <pre><code>#include &lt;iostream&gt;
  #include &lt;vector&gt;
  
  class person
  {
  public:
      std::string m_name;
      explicit person(const std::string &amp;name) : m_name(name)
      {
          std::cout &lt;&lt; &quot;created &quot; &lt;&lt; m_name &lt;&lt; std::endl;     
      }
      
      ~person()
      {
          std::cout &lt;&lt; &quot;destroyed &quot; &lt;&lt; m_name &lt;&lt; std::endl;       
      }   
      
      person(const person &amp;other) : m_name(other.m_name)
      {
          m_name += &quot;.copied&quot;;
          std::cout &lt;&lt; &quot;copied &quot; &lt;&lt; other.m_name &lt;&lt; &quot; -&gt; &quot; &lt;&lt; m_name &lt;&lt; std::endl;
      }
      
      person(const person &amp;&amp;other) noexcept : m_name(std::move(other.m_name))
      {
          m_name += &quot;.moved&quot;;
          std::cout &lt;&lt; &quot;moved &quot; &lt;&lt; other.m_name &lt;&lt; &quot; -&gt; &quot; &lt;&lt; m_name &lt;&lt; std::endl;
      }   
  };
  
  int main()
  {
      std::vector&lt;person&gt; people;
      people.reserve(10);
      
      std::cout &lt;&lt; &quot;\ncopy bob (lvalue):&quot; &lt;&lt; std::endl;
      person bob{&quot;bob&quot;};
      people.push_back(bob);
  
      std::cout &lt;&lt; &quot;\nmove fred (lvalue):&quot; &lt;&lt; std::endl;
      person fred{&quot;fred&quot;};
      people.push_back(std::move(fred));
  
      std::cout &lt;&lt; &quot;\ntemp joe (rvalue):&quot; &lt;&lt; std::endl;
      people.push_back(person{&quot;joe&quot;});
      
      std::cout &lt;&lt; &quot;\nterminating:&quot; &lt;&lt; std::endl;
  }
  </code></pre>
  <p>This gives me the output that I would expect (mostly, except why std::string contents is not &quot;moved&quot;?): <a href="https://godbolt.org/z/-J_56i" rel="nofollow noreferrer">https://godbolt.org/z/-J_56i</a></p>
  <p>Then I remove the std::vector <code>reserve</code> so that std::vector has to &quot;grow&quot; as I am adding elements. Now I get something that I really don't expect: <a href="https://godbolt.org/z/rS6-mj" rel="nofollow noreferrer">https://godbolt.org/z/rS6-mj</a></p>
  <p>Now I can see that bob is copied and then moved when fred is added and then moved again when joe is added. I was under the impression that std::vector &quot;moved&quot; when it has to reallocate space. But I thought that it did a memory copy/move, not an object-by-object copy/move. I really did not expect it to call the move constructor.</p>
  <p>Now if I remove the move c'tor, I find that bob is copied three times!: <a href="https://godbolt.org/z/_BxnvU" rel="nofollow noreferrer">https://godbolt.org/z/_BxnvU</a>
  This seems really inefficient.</p>
  <p>From cplusplus.com:</p>
  <p><strong>push_back()</strong></p>
  <blockquote>
  <p>Add element at the end Adds a new element at the end of the vector,
  after its current last element. The content of val is copied (or
  moved) to the new element.</p>
  <p>This effectively increases the container size by one, which causes an
  automatic reallocation of the allocated storage space if -and only if-
  the new vector size surpasses the current vector capacity.</p>
  </blockquote>
  <p><strong>resize()</strong></p>
  <blockquote>
  <p>Resizes the container so that it contains n elements.</p>
  <p>If n is smaller than the current container size, the content is
  reduced to its first n elements, removing those beyond (and destroying
  them).</p>
  <p>If n is greater than the current container size, the content is
  expanded by inserting at the end as many elements as needed to reach a
  size of n. If val is specified, the new elements are initialized as
  copies of val, otherwise, they are value-initialized.</p>
  <p>If n is also greater than the current container capacity, an automatic
  reallocation of the allocated storage space takes place.</p>
  <p>Notice that this function changes the actual content of the container
  by inserting or erasing elements from it.</p>
  </blockquote>
  <p>I guess it does not really describe &quot;how&quot; it does the reallocation, but surely a memory copy is the fastest way to move the vector to its newly allocated memory space?</p>
  <p>So why are the copy/move c'tors called when std::vector is added to instead of a memory copy?</p>
  <p>A side note/question: (any maybe this should be a separate question): In person move c'tor why is <code>moved fred -&gt; fred.moved</code> printed and not <code>moved -&gt; fred.moved</code>. It appears that the std::string move assignment does not really &quot;move&quot; the data...</p>