// Vector_step1.cpp // // 2017-03-09 //
#include <iostream>
using namespace std;
const unsigned INIT_CAP = 2;
struct Vector
{
size_t len;
size_t cap;
int* ary;
// default ctor ...
Vector() :len(0), cap(0), ary(0) {}
void push_back( int val );
void enlarge();
int operator [] ( size_t i ) const { return ary[i]; }
// so can set new values in the vector //
int& operator [] ( size_t i ) { return ary[i]; }
} ;
// definitions //
void Vector::push_back( int val )
{
if( len == cap ) enlarge();
ary[len] = val;
++ len;
}
void Vector::enlarge()
{
if( cap ) cap += cap; // it gets doubled if had a value
else cap = INIT_CAP;
int* 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 aray memory //
ary = tmp; // update ary pointer to point to new memory //
}
// a little test ... //
void print( const Vector& v )
{
for( size_t i = 0; i < v.len; ++ i )
cout << v[i] << ' ';
cout << "\nThe len = " << v.len
<< ", the cap = " << v.cap << '\n';
}
int main()
{
Vector v;
v.push_back( 6 );
v.push_back( 7 );
v.push_back( 8 );
print( v );
}
// Vector_step2.cpp // // 2017-03-09 //
// Here, in step 2,
// we add "BIG THREE" needed when you use new memory
// 1) destructor ... (that calls a clear method)
// and 2) copy ctor
// and 3) overloaded assignment //
#include <iostream>
using namespace std;
const unsigned INIT_CAP = 2;
struct Vector
{
size_t len;
size_t cap;
int* ary;
// default ctor ...
Vector() :len(0), cap(0), ary(0) {}
// copy ctor ...
Vector( const Vector& 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& operator = ( const Vector& 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( int val );
void enlarge();
int operator [] ( size_t i ) const { return ary[i]; }
// so can set new values in vector //
int& operator [] ( size_t i ) { return ary[i]; }
} ;
// definitions //
void Vector::push_back( int val )
{
if( len == cap ) enlarge();
ary[len] = val;
++ len;
}
void Vector::enlarge()
{
if( cap ) cap += cap; // it gets doubled if had a value
else cap = INIT_CAP;
int* 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 //
}
// a little test ... //
void print( const Vector& v )
{
for( size_t i = 0; i < v.len; ++ i )
cout << v[i] << ' ';
cout << "\nThe len = " << v.len
<< ", the cap = " << v.cap << '\n';
}
int main()
{
Vector v, w;
v.push_back( 6 );
v.push_back( 7 );
v.push_back( 8 );
print( v );
Vector 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.clear();
cout << "After calling w.clear() ...\n";
print( w );
}
// Vector_step3.cpp // // 2017-03-10 //
// Here, in step 3, we do simple and fairly straight-foward
// update to a template class //
#include <iostream>
using namespace std;
const unsigned INIT_CAP = 2;
template< typename T >
class Vector
{
size_t len;
size_t cap;
T* ary;
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 enlarge();
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; }
} ;
// 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 //
}
// a little external print function to aid testing input/output ... //
template< typename T >
void print( const Vector< T >& v )
{
for( size_t i = 0; i < v.size(); ++ i )
cout << v[i] << ' ';
cout << "\nThe size = " << v.size()
<< ", the capacity = " << v.capacity() << '\n';
}
int main()
{
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.clear();
cout << "After calling w.clear() ...\n";
print( w );
}
// 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 );
}
// 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 );
}
// Vector_5_shrink_swap.cpp // // 2017-03-10 //
// Here, in step 5, we add methods shrink and swap //
#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 );
void swap( Vector& vec );
void shrink();
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;
}
template< typename T >
void Vector< T >::swap( Vector& vec )
{
T* aryTmp = vec.ary; // save start address
size_t lenTmp = vec.len;
size_t capTmp = vec.cap;
vec.ary = ary;
vec.len = len;
vec.cap = cap;
ary = aryTmp;
len = lenTmp;
cap = capTmp;
}
template< typename T >
void Vector< T >::shrink()
{
if( len < cap )
{
T* tmp = new T[ len ]; // get 'right-sized' memory //
for( size_t i = 0; i < len; ++ i ) tmp[i] = ary[i];
delete [] ary; // now can delete old memory //
ary = tmp; // update with the address of the new memory //
cap = len;
}
}
// 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.reserve(10);
print( v );
v.push_back( 6 );
v.push_back( 7 );
v.push_back( 8 );
v.shrink();
cout << "After v.reserve(10) and 3 push_backs and calling v.shrink() ...\n";
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.resize(10);
w.push_back( 9 );
cout << "After calling w.resize(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 );
w.swap(v);
cout << "After calling w.swap(v) ... print( w ) is ...\n";
print( w );
cout << "And print( v ) is ...\n";
print( v );
}
// Vector_6_iterators.cpp // // 2017-03-10 //
// Here, in step 6, we add iterators ...
// Also, we separate out our class Vector into its own .h file
// with suitable guards //
#include "Vector.h" // includes <iostream>
// a little external print function to aid testing input/output ... //
template< typename T >
void print( const Vector< T >& v )
{
using std::cout;
typename Vector< T >::const_iterator it;
for( it = v.begin(); it != v.end(); ++ it )
cout << *it << ' ';
cout << "\nThe size = " << v.size()
<< ", the capacity = " << v.capacity() << '\n';
}
int main()
{
using std::cout;
Vector< int > v, w;
v.reserve(10);
print( v );
v.push_back( 6 );
v.push_back( 7 );
v.push_back( 8 );
v.shrink();
cout << "After v.reserve(10) and 3 push_backs and calling v.shrink() ...\n";
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.resize(10);
w.push_back( 9 );
cout << "After calling w.resize(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 );
w.swap(v);
cout << "After calling w.swap(v) ... print( w ) is ...\n";
print( w );
cout << "And print( v ) is ...\n";
print( v );
}
// Vector.h // // 2017-03-10 //
#ifndef VECTOR_2017_03_10_H
#define VECTOR_2017_03_10_H
#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 );
void swap( Vector& );
void shrink();
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; }
typedef T* iterator;
iterator begin() { return ary; }
iterator end() { return ary+len; }
typedef const T* const_iterator;
const_iterator begin() const { return ary; }
const_iterator end() const { return ary+len; }
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;
}
template < typename T >
void Vector< T >::swap( Vector& vec )
{
T* aryTmp = vec.ary; // save start address
size_t lenTmp = vec.len;
size_t capTmp = vec.cap;
vec.ary = ary;
vec.len = len;
vec.cap = cap;
ary = aryTmp;
len = lenTmp;
cap = capTmp;
}
template < typename T >
void Vector< T >::shrink()
{
if( len < cap )
{
T* tmp = new T[ len ]; // get 'right-sized' memory //
for( size_t i = 0; i < len; ++ i ) tmp[i] = ary[i];
delete [] ary; // now can delete old memory //
ary = tmp; // update with the address of the new memory //
cap = len;
}
}
#endif