In step 4 ... (again please see comments at top of program)
// Vector_step4.cpp // // 2017-03-10 //
// Here, in step 4, we add methods reserve and resize
#include <iostream>
const unsigned INIT_CAP = 2;
template< typename T >
class Vector
{
public:
// default ctor ...
Vector() :len(0), cap(0), ary(0) {}
// copy ctor ...
Vector( const Vector< T >& v )
{
len = v.len;
cap = v.cap;
ary = new int[ cap ];
for( size_t i = 0; i < len; ++ i ) ary[i] = v.ary[i];
}
// overloaded assignment ...
Vector< T >& operator = ( const Vector< T >& v )
{
if( this != &v ) // if NOT same addresses //
{
delete [] ary; // since NOT same memory can now do this //
len = v.len;
cap = v.cap;
ary = new int[ cap ];
for( size_t i = 0; i < len; ++ i ) ary[i] = v.ary[i];
}
return *this;
}
// destructor ...
~Vector() { clear(); }
void clear()
{
delete [] ary;
cap = len = 0;
ary = 0; // this fix clears up case of calling destructor after calling clear //
}
void push_back( const T& val );
void reserve( size_t );
void resize( size_t );
const T& operator [] ( size_t i ) const { return ary[i]; } // read only //
// NOT const and returned by ref
// so can set new values inside the vector //
T& operator [] ( size_t i ) { return ary[i]; }
size_t size() const { return len; }
size_t capacity() const { return cap; }
private:
size_t len;
size_t cap;
T* ary;
void enlarge();
} ;
// definitions //
template< typename T >
void Vector< T >::push_back( const T& val )
{
if( len == cap ) enlarge();
ary[len] = val;
++ len;
}
template< typename T >
void Vector< T >::enlarge()
{
if( cap ) cap += cap; // it gets doubled if had a value
else cap = INIT_CAP;
T* tmp = new int[cap]; // get enlarged memory //
for( size_t i = 0; i < len; ++ i ) tmp[i] = ary[i]; // copy over //
delete [] ary; // delete OLD array memory //
ary = tmp; // update ary pointer to point to new memory ///
}
template < typename T >
void Vector< T >::reserve( size_t newCap )
{
if( newCap > cap )
{
cap = newCap;
T* tmp = new T[ cap ];
for( size_t i = 0; i < len; ++i ) tmp[i] = ary[i];
delete [] ary;
ary = tmp; // update the base address of ary
}
}
template < typename T >
void Vector< T >::resize( size_t newSize )
{
if( newSize > len )
{
reserve( newSize );
for( size_t i = len; i < cap; ++ i ) ary[i] = T();
len = newSize;
}
else if( newSize < len )
len = newSize;
}
// a little external print function to aid testing input/output ... //
template< typename T >
void print( const Vector< T >& v )
{
using std::cout;
for( size_t i = 0; i < v.size(); ++ i )
cout << v[i] << ' ';
cout << "\nThe size = " << v.size()
<< ", the capacity = " << v.capacity() << '\n';
}
int main()
{
using std::cout;
Vector< int > v, w;
v.push_back( 6 );
v.push_back( 7 );
v.push_back( 8 );
print( v );
Vector< int > x(v); // calling copy ctor //
cout << "After calling Vector x(v) ...\n";
print( x );
w = x; // call overloaded assignemnt //
cout << "After calling w = x ...\n";
print( w );
w.reserve(10);
w.push_back( 9 );
cout << "After calling w.reserve(10) and w.push_back(9) ...\n";
print( w );
w.resize(6);
cout << "After calling w.resize(6)...\n";
print( w );
w.resize(3);
cout << "After calling w.resize(3)...\n";
print( w );
w.clear();
cout << "After calling w.clear() ...\n";
print( w );
}
A test to check-out a specific case of resize method ...
// Vector_4_test_resize.cpp // // 2017-03-10 //
// Here, in step 4, we add specific test of resize //
#include <iostream>
const unsigned INIT_CAP = 2;
template< typename T >
class Vector
{
public:
// default ctor ...
Vector() :len(0), cap(0), ary(0) {}
// copy ctor ...
Vector( const Vector< T >& v )
{
len = v.len;
cap = v.cap;
ary = new int[ cap ];
for( size_t i = 0; i < len; ++ i ) ary[i] = v.ary[i];
}
// overloaded assignment ...
Vector< T >& operator = ( const Vector< T >& v )
{
if( this != &v ) // if NOT same addresses //
{
delete [] ary; // since NOT same memory can now do this //
len = v.len;
cap = v.cap;
ary = new int[ cap ];
for( size_t i = 0; i < len; ++ i ) ary[i] = v.ary[i];
}
return *this;
}
// destructor ...
~Vector() { clear(); }
void clear()
{
delete [] ary;
cap = len = 0;
ary = 0; // this fix clears up case of calling destructor after calling clear //
}
void push_back( const T& val );
void reserve( size_t );
void resize( size_t );
const T& operator [] ( size_t i ) const { return ary[i]; } // read only //
// NOT const and returned by ref
// so can set new values inside the vector //
T& operator [] ( size_t i ) { return ary[i]; }
size_t size() const { return len; }
size_t capacity() const { return cap; }
private:
size_t len;
size_t cap;
T* ary;
void enlarge();
} ;
// definitions //
template< typename T >
void Vector< T >::push_back( const T& val )
{
if( len == cap ) enlarge();
ary[len] = val;
++ len;
}
template< typename T >
void Vector< T >::enlarge()
{
if( cap ) cap += cap; // it gets doubled if had a value
else cap = INIT_CAP;
T* tmp = new int[cap]; // get enlarged memory //
for( size_t i = 0; i < len; ++ i ) tmp[i] = ary[i]; // copy over //
delete [] ary; // delete OLD array memory //
ary = tmp; // update ary pointer to point to new memory ///
}
template < typename T >
void Vector< T >::reserve( size_t newCap )
{
if( newCap > cap )
{
cap = newCap;
T* tmp = new T[ cap ];
for( size_t i = 0; i < len; ++i ) tmp[i] = ary[i];
delete [] ary;
ary = tmp; // update the base address of ary
}
}
template < typename T >
void Vector< T >::resize( size_t newSize )
{
if( newSize > len )
{
reserve( newSize );
for( size_t i = len; i < cap; ++ i ) ary[i] = T();
len = newSize;
}
else if( newSize < len )
len = newSize;
}
// a little external print function to aid testing input/output ... //
template< typename T >
void print( const Vector< T >& v )
{
using std::cout;
for( size_t i = 0; i < v.size(); ++ i )
cout << v[i] << ' ';
cout << "\nThe size = " << v.size()
<< ", the capacity = " << v.capacity() << '\n';
}
int main()
{
using std::cout;
Vector< int > v, w;
v.resize(10);
print( v );
v.push_back( 6 );
v.push_back( 7 );
v.push_back( 8 );
print( v );
Vector< int > x(v); // calling copy ctor //
cout << "After calling Vector x(v) ...\n";
print( x );
w = x; // call overloaded assignemnt //
cout << "After calling w = x ...\n";
print( w );
w.reserve(10);
w.push_back( 9 );
cout << "After calling w.reserve(10) and w.push_back(9) ...\n";
print( w );
w.resize(6);
cout << "After calling w.resize(6)...\n";
print( w );
w.resize(3);
cout << "After calling w.resize(3)...\n";
print( w );
w.clear();
cout << "After calling w.clear() ...\n";
print( w );
}