Free, tested & ready to use examples!
AnyExample.com
 
Web anyexample.com
 

C++ dynamic array template class

abstract 
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.
compatible 
  • Any modern C++ compiler
  • AeDynArray class interface is quite simple. There are two constructors(default constructor and copy constructor), assignment operator, overloaded index [] operator and following member functions:

    • Add(el item) — adds item to the end of array, resizes it twice its current capacity if there is no more space
    • GetSize() — returns current size of an array
    • SetSize(unsigned int size) — sets array size
    • Fill(int c) — fills all array's memory with a given integer
    • Clear() — removes all elemets from the array, resets memory alocation
    • Delete(unsigned int pos) — deletes specified element from the array

    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;
    } 
     


    warning 
  • In majority of real-life applications you sould use STL vector class for dynamic arrays, since it provides more detailed and reliabile implementation
  • As you may see in operator [] source code, AeDynArray arrays doesn't have boundary checking.
  • AeDynArray class is not suitable for storing custom C++ objects(with constructors), becase of low-level memory access functions (malloc, memcpy, realloc). It can handle only basic types (char, int, double, float) and structs based on basic types.
  • tested 
  • Windows XP :: Microsoft Visual C++ 2003
  • Free BSD 5.2 :: gcc 3.3.3
  • Mac OS X 10.4.8 :: gcc 4.0.1
  •  


     
    © AnyExample 2010-2013
    License | Privacy | Contact