AnyFormat.io - convert files and webpages to any format!
This article provides example of dynamic array implementation using C++ templates. It uses standard malloc/realloc memory allocation functions and simple "doubling size" resizing strategy. Our AeDynArray class interface resembles MFC standard CArray class, but uses only standard C libraries.
AeDynArray class interface is quite simple. There are two constructors(default constructor and copy constructor), assignment operator, overloaded index [] operator and following member functions:
AeDynArray class difinition is prefixed by the keyword template: el is a type parameter — it can be any type. Functions Add() and operator [] uses type el specified while instantiating a class. source code: C++ #include <cstdlib> template<class el> class AeDynArray { public: AeDynArray(); // constructor AeDynArray(const AeDynArray &a); // copy constructor ~AeDynArray(); // distructor AeDynArray& operator = (const AeDynArray &a); // assignment operator el& operator [] (unsigned int index); // get array item void Add(const el &item); // Add item to the end of array unsigned int GetSize(); // get size of array (elements) void SetSize(unsigned int newsize); // set size of array (elements) void Clear(); // clear array void Delete(unsigned int pos); // delete array item void* getptr(); // get void* pointer to array data enum exception { MEMFAIL }; // exception enum private: el *array; // pointer for array's memory unsigned int size; // size of array (elemets) unsigned int realsize; // actual size of allocated memory const static int dyn_array_step = 128; // initial size of array memory (elements) const static int dyn_array_mult = 2; // multiplier (enlarge array memory // dyn_array_mult times ) }; ////////////////////////////////////////////////////////////////////// template <class el> AeDynArray<el>::AeDynArray() { realsize = dyn_array_step; // First, allocate step // for dyn_array_step items size = 0; array = (el *)malloc(realsize*sizeof(el)); if (array == NULL) throw MEMFAIL; } template <class el> AeDynArray<el>::~AeDynArray() { if (array) { free(array); // Freeing memory array = NULL; } } template <class el> AeDynArray<el>::AeDynArray(const AeDynArray &a) { array = (el *)malloc(sizeof(el)*a.realsize); if (array == NULL) throw MEMFAIL; memcpy(array, a.array, sizeof(el)*a.realsize); // memcpy call -- coping memory contents realsize = a.realsize; size = a.size; } template <class el> AeDynArray<el>& AeDynArray<el>::operator = (const AeDynArray &a) { if (this == &a) // in case somebody tries assign array to itself return *this; if (a.size == 0) // is other array is empty -- clear this array Clear(); SetSize(a.size); // set size memcpy(array, a.array, sizeof(el)*a.size); return *this; } template <class el> unsigned int AeDynArray<el>::GetSize() { return size; // simply return size } template <class el> void AeDynArray<el>::SetSize(unsigned int newsize) { size = newsize; if (size != 0) { // change array memory size // if new size is larger than current // or new size is less then half of the current if ((size > realsize) || (size < realsize/2)) { realsize = size; array = (el *)realloc(array, sizeof(el)*size); if (array == NULL) throw MEMFAIL; } } else Clear(); } template <class el> void AeDynArray<el>::Delete(unsigned int pos) { if (size == 1) // If array has only one element Clear(); // than we clear it, since it will be deleted else { // otherwise, shift array elements for(unsigned int i=pos; i<size-1; i++) array[i] = array[i+1]; // decrease array size size--; } } template <class el> void AeDynArray<el>::Clear() // clear array memory { size = 0; array = (el *)realloc(array, sizeof(el)*dyn_array_step); // set initial memory size again realsize = dyn_array_step; } template <class el> void* AeDynArray<el>::getptr() { return array; // return void* pointer } template <class el> el& AeDynArray<el>::operator [] (unsigned int index) { return array[index]; // return array element } template <class el> void AeDynArray<el>::Add(const el &item) { size++; if (size > realsize) { realsize *= dyn_array_mult; array = (el *)realloc(array, sizeof(el)*realsize); if (array == NULL) throw MEMFAIL; } array[size-1] = item; } Since majority of C++ doesn't support separation of template classes, you should save all source code to a single .h file You may also download ready to use aedynarray.h and include it with your project. To illustrate class usage, here is a program which do various array opration on AeDynArray<int> (array of integers) source code: C++ #include "aedynarray.h" #include <iostream> using namespace std; // function for outputting array items void output_array(AeDynArray<int> &array) { for(unsigned int i=0; i<array.GetSize(); i++) cout << array[i] << ", "; cout << endl; } int main(void) { AeDynArray<int> array; // setting array size array.SetSize(15); // filling array with pseudo-random values for(unsigned int i=0; i<15; i++) array[i] = rand() % 100; // lets add some values using Add() array.Add(7); array.Add(94); array.Add(1); // output all array items output_array(array); // delete 1-st and last items array.Delete(0); array.Delete(array.GetSize() - 1); // output all array items (again) output_array(array); // let's sort all array items using extemly ineffective sort for(unsigned int i=0; i<array.GetSize();) if (array[i] > array[i+1]) { int x = array[i]; array[i] = array[i+1]; array[i+1] = x; i = 0; continue; } else i++; output_array(array); // create another array, based on first AeDynArray<int> array2(array); array2.Clear(); // clear it // check multiple addition for(int i=0; i<1000000; i++) array2.Add(rand()); // check assigment operator array = array2; // output array cout << "array 2 size " << array2.GetSize() << endl; cout << "array 1 size " << array.GetSize() << endl; // check random element int testel = rand() % 1000000; cout << "array 2 element " << testel << " = " << array2[testel] << endl; cout << "array 1 element " << testel << " = " << array[testel] << endl; // that's all! return 0; }
|
|