I understand how an rvalue would invoke the move constructor and move assignment operator, however I'm confused why the same code in Stroustrup's example below for move assignment isn't used for the move constructor. This is from C++ 4th Ed. Page 379 revised errata.
As all the objects in the class are copied in the move constructor, why can't the move constructor simply swap pointers of the object like the move assignment operator?
Perhaps I'm missing something and appreciate your guidance!
template<typename T, typename A = allocator<T>>
struct vector_base { // memory structure for vector
A alloc; // allocator
T* elem; // start of allocation
T* space; // end of element sequence, start of space allocated for possible expansion
T* last; // end of allocated space
vector_base(const A& a, typename A::size_type n, typename A::size_type m =0)
: alloc{a}, elem{alloc.allocate(n+m)}, space{elem+n}, last{elem+n+m} { }
~vector_base() { alloc.deallocate(elem,last-elem); }
vector_base(const vector_base&) = delete; // no copy operations
vector_base& operator=(const vector_base&) = delete;
vector_base(vector_base&&); // move operations
vector_base& operator=(vector_base&&);
};
template<typename T, typename A>
vector_base<T,A>::vector_base(vector_base&& a)
: alloc{a.alloc},
elem{a.elem},
space{a.space},
last{a.last}
{
a.elem = a.space = a.last = nullptr; // no longer owns any memory
}
template<typename T, typename A>
vector_base<T,A>& vector_base<T,A>::operator=(vector_base&& a)
{
swap(*this,a);
return *this;
}
The move constructor cannot do a swap because it's members are uninitialized and the destructor will not work correctly on the passed rvalue. Therefore the move constructor must copy each element one by one and set the rvalue's members to null, so the rvalue destructor will work. The move assignment can do the swap with the rvalue, because the when the rvalue destructor is invoked the data will be valid (and be the data from the regular constructor of the potential lvalue).