Why explicit memory management complicates our implementation
Let’s look for a moment at one of the constructors for Vector<T> as written in Chapter 12. For simplicity, we will use the constructor that accepts a number of elements and an initial value for these elements as arguments. If we limit ourselves to the naïve version where elems points to a sequence of T objects and put aside for the moment the more sophisticated version where elems points to a block of memory that holds T objects at the beginning and raw memory at the end, we have the following:
// naïve version with elems of type T*
Vector(size_type n, const_reference init)
: elems{ new value_type[n] }, nelems{ n }, cap{ n } {
try {
std::fill(begin(), end(), init);
} catch (...) {
&...