title: why is the destructor call after the std::move necessary?
body: <p>In The C++ programming language Edition 4 there is an example of a vector implementation, see relevant code at the end of the message.</p>
  
  <p><strong>uninitialized_move()</strong> initializes new T objects into the new memory area by moving them from the old memory area. Then it calls the destructor on the original T object, the moved-from object. Why is the destructor call necessary in this case?</p>
  
  <p>Here is my incomplete understanding: moving an object means that the ownership of the resources owned by the moved-from object are transferred to the moved-to object. The remainings in the moved-from object are some possible members of built-in types that do not need to be destroyed, they will be deallocated when the the vector_base b goes out of scope (inside <strong>reserve()</strong>, after the <strong>swap()</strong> call). All pointers in the moved-from object are to be put to nullptr or some mechanism is employed to drop ownership of moved-from object on those resources so that we are safe, then why call the destructor on a depleted object when the "vector_base b" destructor will anyway deallocate the memory after the swap is done?</p>
  
  <p>I understand the need to explicitly call the destructor in the cases when it must be called because we have something to destruct (e.g. drop elements) but I fail to see its meaning after the std::move + deallocation of vector_base. I read some texts on the net  and I'm seeing the destructor call of the moved-from object as an signal (to whom or what?) that the lifetime of the object is over.</p>
  
  <p>Please clarify to me what meaningful work remains to be done by the destructor? Thank you!</p>
  
  <p>The code snippet below is from here <a href="http://www.stroustrup.com/4th_printing3.html" rel="noreferrer">http://www.stroustrup.com/4th_printing3.html</a></p>
  
  <pre><code>template&lt;typename T, typename A&gt;
  void vector&lt;T,A&gt;::reserve(size_type newalloc)
  {
      if (newalloc&lt;=capacity()) return;                   // never decrease allocation
      vector_base&lt;T,A&gt; b {vb.alloc,size(),newalloc-size()};   // get new space
      uninitialized_move(vb.elem,vb.elem+size(),b.elem);  // move elements
      swap(vb,b);                                 // install new base 
  } // implicitly release old space
  
  template&lt;typename In, typename Out&gt;
  Out uninitialized_move(In b, In e, Out oo)
  {
      using T = Value_type&lt;Out&gt;;      // assume suitably defined type function (_tour4.iteratortraits_, _meta.type.traits_)
      for (; b!=e; ++b,++oo) {
          new(static_cast&lt;void*&gt;(&amp;*oo)) T{move(*b)};  // move construct
          b-&gt;~T();                                // destroy
      }
      return oo;       
  }
  </code></pre>