Free, tested & ready to use examples : C++ dynamic array template malloc realloc STL MFC CArray [] operator
AnyExample.com
 
Webanyexample.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 by AnyExample.com on 2007-04-13
  • 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 2007
License | Privacy | Contact