A Generic Vector Class Andy Wang Data Structures

  • Slides: 35
Download presentation
A Generic Vector Class Andy Wang Data Structures, Algorithms, and Generic Programming

A Generic Vector Class Andy Wang Data Structures, Algorithms, and Generic Programming

Contact Information w Andy Wang (awang@cs. fsu. edu) w LOV 264 w Office hours:

Contact Information w Andy Wang (awang@cs. fsu. edu) w LOV 264 w Office hours: M 1: 30 pm – 2: 30 pm Th 2: 00 pm – 3: 00 pm w Class website: http: //www. cs. fsu. edu/~awang/courses/cop 4530_f 2003

Idea: A Generic Array… w Of an arbitrary type (generic container) w A template

Idea: A Generic Array… w Of an arbitrary type (generic container) w A template class w Set and change the array size at runtime w Index bounds checking w Automatic memory management

TVector<T> TVector<int> int. Vector(10); TVector<char> char. Vector(30); TVector<pair<char> > char. Pair. Vector(20); int. Vector.

TVector<T> TVector<int> int. Vector(10); TVector<char> char. Vector(30); TVector<pair<char> > char. Pair. Vector(20); int. Vector. set_size(50);

TVector<T> Interface w Constructor(s)/destructor w Operators n n [] = w Accessor functions n

TVector<T> Interface w Constructor(s)/destructor w Operators n n [] = w Accessor functions n n Set vector size Set storage capacity (reserve memory)

TVector<T> Implementation w A protected C array to store the array content w Protected

TVector<T> Implementation w A protected C array to store the array content w Protected data members n n Size // the number of used array elements Capacity // total storage capacity w A protected method that allocates memory w Manage memory and data when appropriate

Code Layout w tvector. h w tvector. cpp

Code Layout w tvector. h w tvector. cpp

tvector. h #ifndef _TVECTOR_H #define _TVECTOR_H #include <stdlib. h> #include <iostream> namespace rcl {

tvector. h #ifndef _TVECTOR_H #define _TVECTOR_H #include <stdlib. h> #include <iostream> namespace rcl { // class definition #include “tvector. cpp” // class implementation }; #endif // _TVECTOR_H

tvector. cpp #ifndef _TVECTOR_CPP // now a part of the tvector. h #define _TVECTOR_CPP

tvector. cpp #ifndef _TVECTOR_CPP // now a part of the tvector. h #define _TVECTOR_CPP static const unsigned int default_capacity = 10; // operator overloads // public methods // protected methods #endif // _TVECTOR_CPP • Scope: file • Need to be initialized at the time of declaration • Cannot be changed

main. cpp #include “tvector. h” // which includes tvector. cpp using namespace rcl; Tvector<int>

main. cpp #include “tvector. h” // which includes tvector. cpp using namespace rcl; Tvector<int> int. Vector();

Class TVector<T> template <typename T> class Tvector { public: // constructors/deconstructor // operators //

Class TVector<T> template <typename T> class Tvector { public: // constructors/deconstructor // operators // accessor functions protected: // data // method }; // operator overloads

Class TVector<T> template <typename T> class TVector { public: // constructors/deconstructor TVector(); // default

Class TVector<T> template <typename T> class TVector { public: // constructors/deconstructor TVector(); // default constructor TVector(size_t); TVector(const TVector<T>&); // copy constructor ~TVector(); // operators TVector<T>& operator= (const TVector<T>&); T& operator[] (size_t) const; // sizing int Set. Size(size_t, const T&); int Set. Capacity(size_t); size_t Size() const; size_t Capacity() const;

Class TVector<T> // container class protocol int Empty() const; // return 1 if the

Class TVector<T> // container class protocol int Empty() const; // return 1 if the array is empty int Push. Back(const T&); // add an element to array[size] int Pop. Back(); // remove the element from array[size - 1] void Clear(); T& Front() const; T& Back() const; // generic display methods void Display(ostream os, char ofs = ‘’) const; void Dump(ostream& os) const; protected: size_t size, capacity; // array size and storage capacity T* content; // pointer to array elements static T* newarray(size_t); // allocate memory }; // operator overloads

Class TVector<T> template <typename T> class TVector { public: // constructors/deconstructor TVector(); // default

Class TVector<T> template <typename T> class TVector { public: // constructors/deconstructor TVector(); // default constructor TVector(size_t); TVector(const TVector<T>&); // copy constructor ~TVector(); // operators TVector<T>& operator= (const TVector<T>&); T& operator[] (size_t) const; // sizing int Set. Size(size_t, const T&); int Set. Capacity(size_t); size_t Size() const; size_t Capacity() const; Implicit copies • value = f(); • f(value);

Class TVector<T> template <typename T> class TVector { public: // constructors/deconstructor TVector(); // default

Class TVector<T> template <typename T> class TVector { public: // constructors/deconstructor TVector(); // default constructor TVector(size_t); TVector(const TVector<T>&); // copy constructor ~TVector(); // operators TVector<T>& operator= (const TVector<T>&); T& operator[] (size_t) const; // sizing int Set. Size(size_t, const T&); int Set. Capacity(size_t); size_t Size() const; size_t Capacity() const; Read accessor functions

Class TVector<T> template <typename T> class TVector { public: // constructors/deconstructor TVector(); // default

Class TVector<T> template <typename T> class TVector { public: // constructors/deconstructor TVector(); // default constructor TVector(size_t); TVector(const TVector<T>&); // copy constructor ~TVector(); // operators TVector<T>& operator= (const TVector<T>&); T& operator[] (size_t) const; // sizing int Set. Size(size_t, const T&); int Set. Capacity(size_t); size_t Size() const; size_t Capacity() const; Write accessor functions

Class TVector<T> template <typename T> class TVector { public: // constructors/deconstructor TVector(); // default

Class TVector<T> template <typename T> class TVector { public: // constructors/deconstructor TVector(); // default constructor TVector(size_t); TVector(const TVector<T>&); // copy constructor ~TVector(); // operators TVector<T>& operator= (const TVector<T>&); T& operator[] (size_t) const; // sizing int Set. Size(size_t, const T&); int Set. Capacity(size_t); size_t Size() const; size_t Capacity() const; Explicit copies

Class TVector<T> template <typename T> class TVector { public: // constructors/deconstructor TVector(); // default

Class TVector<T> template <typename T> class TVector { public: // constructors/deconstructor TVector(); // default constructor TVector(size_t); TVector(const TVector<T>&); // copy constructor ~TVector(); // operators TVector<T>& operator= (const TVector<T>&); T& operator[] (size_t) const; // sizing int Set. Size(size_t, const T&); int Set. Capacity(size_t); size_t Size() const; size_t Capacity() const; Returns a reference, so the element can be modified on the left side of an assignment

Class TVector<T> // container class protocol int Empty() const; // return 1 if the

Class TVector<T> // container class protocol int Empty() const; // return 1 if the array is empty int Push. Back(const T&); // add an element to array[size] int Pop. Back(); // remove the element from array[size - 1] void Clear(); // clear the array T& Front() const; // returns array[0] T& Back() const; // returns array[size – 1] // generic display methods void Display(ostream os, char ofs = ‘’) const; void Dump(ostream& os) const; Debugging Functions protected: size_t size, capacity; // array size and storage capacity T* content; // pointer to array elements static T* newarray(size_t); // allocate memory }; // operator overloads

Class TVector<T> // container class protocol int Empty() const; // return 1 if the

Class TVector<T> // container class protocol int Empty() const; // return 1 if the array is empty int Push. Back(const T&); // add an element to array[size] int Pop. Back(); // remove the element from array[size - 1] void Clear(); // clear the array T& Front() const; // returns array[0] T& Back() const; // returns array[size – 1] // generic display methods void Display(ostream os, char ofs = ‘’) const; void Dump(ostream& os) const; protected: size_t size, capacity; // array size and storage capacity T* content; // pointer to array elements static T* newarray(size_t); // allocate memory }; // operator overloads Scope: tvector. h and tvector. cpp

Operator Overloads template <typename T> ostream& operator<< (ostream& os, const TVector<T>& a); template <typename

Operator Overloads template <typename T> ostream& operator<< (ostream& os, const TVector<T>& a); template <typename T> int operator== (const TVector<T>&, const TVector<T>&); template <typename T> int operator!= (const TVector<T>&, const TVector<T>&);

TVector<T> newarray() template <typename T> T* TVector<T>: : newarray(size_t newcapacity) { T* Tptr =

TVector<T> newarray() template <typename T> T* TVector<T>: : newarray(size_t newcapacity) { T* Tptr = 0; if (newcapacity > 0) { Tptr = new T[newcapacity]; if (Tptr == 0) { cerr << “memory allocation failed” << endl; } } return Tptr; } A reusable routine called by constructor and size functions

Constructors template <typename T> TVector<T>: : TVector() : size(0), capacity(default_capacity), content(0) { content =

Constructors template <typename T> TVector<T>: : TVector() : size(0), capacity(default_capacity), content(0) { content = newarray(capacity); } template <typename T> TVector<T>: : TVector(unsigned int sz) : size(sz), capacity(sz) { content = newarray(capacity); } template <typename T> TVector<T>: : TVector(const TVector<T>& source) : size(source. size), capacity(source. capacity) { content = newarray(capacity); for (size_t j = 0; j < size; ++j) { content[j] = source. content[j]; } }

Destructor template <typename T> TVector<T>: : ~TVector() { delete [] content; }

Destructor template <typename T> TVector<T>: : ~TVector() { delete [] content; }

Debugging Routines template <typename T> void TVector<T>: : Display(ostream& os, char ofc) const {

Debugging Routines template <typename T> void TVector<T>: : Display(ostream& os, char ofc) const { size_t j; if (ofc == ‘’) { for (j = 0; j < size; ++j) {os << content[j]; } } else { for (j = 0; j < size; ++j) {os << content[j] << ofc; } } }

Debugging Routines (2) template <typename T> void TVector<T>: : Dump(ostream& os) const { size_t

Debugging Routines (2) template <typename T> void TVector<T>: : Dump(ostream& os) const { size_t j; if (size == 0) { os << “()”; } else { os << “(“; for (j = 1; j < size; ++j) { os << ‘, ’ << content[j]; } os << “)”; } }

Read Accessor Functions template <typename T> size_t TVector<T>: : Size() const { return size;

Read Accessor Functions template <typename T> size_t TVector<T>: : Size() const { return size; } template <typename T> size_t TVector<T>: : Capacity() const { return capacity; }

Read Accessor Functions (2) template <typename T> T& TVector<T>: : Front() const { //

Read Accessor Functions (2) template <typename T> T& TVector<T>: : Front() const { // report error and exit if size is zero return content[0]; } template <typename T> T& TVector<T>: : Back() const { // report error and exit if size is zero return content[size - 1]; }

Write Accessor Functions template <typename T> int TVector<T>: : Set. Capacity(size_t newcapacity) { if

Write Accessor Functions template <typename T> int TVector<T>: : Set. Capacity(size_t newcapacity) { if (newcapacity == 0) { // delete content and set internal states to zero return 1; } if (newcapacity != capacity) { T* newcontent = newarray(newcapacity); if (newcontent == 0) return 0; if (size > newcapacity) size = newcapacity; for (size_t j = 0; j < size; ++j) { newcontent[j] = content[j]; } capacity = newcapacity; delete [] content; content = newcontent; } return 1; }

Write Accessor Functions (2) template <typename T> int TVector<T>: : Set. Size(size_t newsize) {

Write Accessor Functions (2) template <typename T> int TVector<T>: : Set. Size(size_t newsize) { if (newsize > capacity) { if (Set. Capacity(newsize) == 0) { return 0; } } size = newsize; return 1; } template <typename T> int TVector<T>: : Clear() { Set. Size(0); }

Write Accessor Functions (3) template <typename T> int TVector<T>: : Push. Back(const T& Tval)

Write Accessor Functions (3) template <typename T> int TVector<T>: : Push. Back(const T& Tval) { // expand the content array when size > capacity // expand the content array by doubling // call Set. Capacity() to expand content // special case when capacity is zero—doubling zero is zero! // return 1 on success, 0 on failure } template <typename T> int TVector<T>: : Pop. Back() { if (size == 0) return 0; --size; return 1; }

Operators template <typename T> TVector<T>& TVector<T>: : operator= (const TVector<T>& source) { if (this

Operators template <typename T> TVector<T>& TVector<T>: : operator= (const TVector<T>& source) { if (this != &source) { if (source. capacity == 0) { if (capacity > 0) delete [] content; // set private data members to zero return *this; } if (capacity != source. capacity) { if (capacity > 0) delete [] content; capacity = source. capacity; content = newarray(capacity); } size = source. size; // copy content from source. content } return *this; }

Operators (2) template <typename T> T& TVector<T>: : operator[] (size_t j) const { if

Operators (2) template <typename T> T& TVector<T>: : operator[] (size_t j) const { if (j >= size) { cerr << “vector index out of range!” << endl; if (j >= capacity) { exit(EXIT_FAILURE); } } return content[j]; }

Operator Overloads template <typename T> ostream& operator<< (ostream& os, const TVector<T>& v) { v.

Operator Overloads template <typename T> ostream& operator<< (ostream& os, const TVector<T>& v) { v. Display(os); return(os); } template <typename T> int operator!=(const TVector<T>& v 1, const TVector<T>& v 2) { return !(v 1 == v 2); }

Operator Overloads (2) template <typename T> int operator==(const TVector<T>& v 1, const TVector<T>& v

Operator Overloads (2) template <typename T> int operator==(const TVector<T>& v 1, const TVector<T>& v 2) { if (v 1. Size() != v 2. Size() { return 0; } for (size_t j = 0; j < v 1. Size(); ++j) { if (v 1[j] != v 2[j]) return 0; } return 1; }