Dynamic array of std::string

Started by
9 comments, last by Decrius 13 years, 10 months ago
I have written a small array class to handle dynamic arrays of objects. I did it mostly for speed. But I am running into problems with memcpy and std::string.

I use a function called adjust pointer which just allocates a new array, copies the old one into it and deletes the old one.

template <class T> void cGhost :: AdjustPointer(T *&Var, int &Size, int Increment){	if (Increment < 0)	{		if (Size + Increment < 1)		{			if (Var == NULL)				return;			else			{				SAFE_DELETE_ARRAY(Var);				Size = 0;				return;			}		}	}	T *New = new T[Size + Increment];	memcpy(&New[0], &Var[0], sizeof(T) * Size);	SAFE_DELETE_ARRAY(Var);	Var = New;	Size += Increment;}


But I am running into problems with strings. It doesn't seem to copy properly and I ended up having to use a for loop and set each iteration directly. I'm guessing it has something to do with the how the string stores it array of chars. Maybe a copy constructor is needed with strings? I'm not sure. I've spent a long time looking up this problem and I can't seem to find any solution.

Here's the array class for reference.

#pragma once#include "GhostVars.h"template<class T>class cArray{public:	cArray(void)	{		Array = NULL;		Size = 0;		Increment = 1;		Last = 0;		CurIndex = 0;		AutoDelete = true;	}	cArray(int size, int inc = 1, bool autodelete = true)	{		Array = NULL;		Size = 0;		Increment = inc;		Last = 0;		CurIndex = 0;		AutoDelete = autodelete;		Increase(size);	}	cArray(const cArray &cA)	{		Array = cA.Array;		Size = cA.Size;		Increment = cA.Increment;		Last = cA.Last;		CurIndex = cA.CurIndex;		AutoDelete = cA.AutoDelete;	}	~cArray(void)	{		if (AutoDelete) 			SAFE_DELETE_ARRAY(Array);	}	void Insert(const T &In, const int &Index);	void Delete(const int &Index);		void InsertSafe(const T &In, const int &Index);	void DeleteSafe(const int &Index);	__inline void Clear() { if (Size > 0) { SAFE_DELETE_ARRAY(Array); Size = 0; } }	__inline T& operator[](const int &Index) { return Array[Index]; }	__inline T *Get(const int &Index) { return &Array[Index]; }	__inline T *GetFirst() { return &Array[0]; }	__inline T *GetLast() { return &Array[Last]; }	__inline bool GetSafe(T &Out, const int &Index) { if (Index >= 0 && Index < Size) { Out = Array[Index]; return true; } else return false; }	__inline bool GetSafeFirst(T &Out) { if (Size > 0) { Out = Array[0]; return true; } else return false; }	__inline bool GetSafeLast(T &Out) { if (Size > 0) { Out = Array[Last]; return true; } else return false; }	__inline const int &GetSize() { return Size; }	__inline const int &GetIncrement() { return Increment; }	__inline const int &GetFilledSize() { return CurIndex; }	__inline void operator++() { Ghost->AdjustPointer(Array, Size, 1); Last = Size - 1; }	__inline void operator--() { Ghost->AdjustPointer(Array, Size, -1); Last = Size - 1; }	__inline void Increase(int inc = 0) { if (inc == 0) inc = Increment; Ghost->AdjustPointer(Array, Size, inc); Last = Size - 1;}	__inline void Decrease(int inc = 0) { if (inc == 0) inc = -Increment; Ghost->AdjustPointer(Array, Size, inc); Last = Size - 1;}	__inline void Push(const T &In) { Ghost->AdjustPointer(Array, Size, 1); Last = Size - 1; Array[Last] = In; }	__inline void Fill(const T &In) { Array[CurIndex] = In; ++CurIndex;  if (CurIndex >= Size) Increase(); }	__inline bool IsValidIndex(const int &Index) { return (Index >= 0 && Index < Size); }	__inline void SetAutoDelete(const bool &In) { AutoDelete = In; }	__inline void SetIncrement(const int &i) { if (i != 0) Increment = i; }	__inline void SetCurIndex(const int &i = 0) { if (IsValidIndex(i)) CurIndex = i; }private:	T *Array;	int Size;	int Increment;	int Last;	int CurIndex;	bool AutoDelete;};template<class T> void cArray<T> :: Insert(const T &In, const int &Index){	T *NewArray = new T[Size + 1];	memcpy(&NewArray[0], &Array[0], sizeof(T) * Index);	NewArray[Index] = In;	memcpy(&NewArray[Index + 1], &Array[Index], sizeof(T) * Size - Index);	SAFE_DELETE_ARRAY(Array);	Array = NewArray;	++Size;}template<class T> void cArray<T> :: Delete(const int &Index){	if (Size == 1)	{		SAFE_DELETE_ARRAY(Array);		Size = 0;		return;	}	--Size;	T *NewArray = new T[Size];	if (Index != 0 && Index < Size)	{		memcpy(&NewArray[0], &Array[0], sizeof(T) * Index);		memcpy(&NewArray[Index], &Array[Index + 1], sizeof(T) * (Size - Index));	}	else if (Index == 0)		memcpy(&NewArray[0], &Array[1], sizeof(T) * (Size));	else if (Index == Size)		memcpy(&NewArray[0], &Array[0], sizeof(T) * (Size));	SAFE_DELETE_ARRAY(Array);	Array = NewArray;}template<class T> void cArray<T> :: InsertSafe(const T &In, const int &Index){	if (Index >= 0 && Index < Size)	{		T *NewArray = new T[Size + 1];		memcpy(&NewArray[0], &Array[0], sizeof(T) * Index);		NewArray[Index] = In;		memcpy(&NewArray[Index + 1], &Array[Index], sizeof(T) * Size - Index);		SAFE_DELETE_ARRAY(Array);		Array = NewArray;		++Size;	}}template<class T> void cArray<T> :: DeleteSafe(const int &Index){	if (Index >= 0 && Index < Size)	{		if (Size == 1)		{			SAFE_DELETE_ARRAY(Array);			Size = 0;			return;		}		--Size;		T *NewArray = new T[Size];		if (Index != 0 && Index < Size)		{			memcpy(&NewArray[0], &Array[0], sizeof(T) * Index);			memcpy(&NewArray[Index], &Array[Index + 1], sizeof(T) * (Size - Index));		}		else if (Index == 0)			memcpy(&NewArray[0], &Array[1], sizeof(T) * (Size));		else if (Index == Size)			memcpy(&NewArray[0], &Array[0], sizeof(T) * (Size));		SAFE_DELETE_ARRAY(Array);		Array = NewArray;	}}


Any help would be great!

Thanks,
Jake
Advertisement
Don't use memcpy. Use std::copy like this:
std::copy(Var, Var + Size, New);


In general - you are not allowed to use memcpy with non-POD structs/classes.
Thank you so much!! Why didn't I think of that... :D
Is there any reason why you're not using the standard dynamic array, std::vector? The STL library has been thoroughly tested and debugged by millions of developers, while your custom dynamic array, may end up being slower, more buggy, and less efficient, if not as fast and as efficient as the STL's own containers. For instance, your array class re-allocates and copies all of the elements into an array of a different size for every time you add an element to the array or remove an element from the array.
I found that vectors are not so fast when not using iterators. Using the [] operator is very slow. But maybe I am doing something wrong? I also wrote this class as a learning experience. I find that writing my own class helps me understand things better.
Quote:Original post by jake_Ghost
I found that vectors are not so fast when not using iterators. Using the [] operator is very slow. But maybe I am doing something wrong?


Depends. Did you compile your project in with or without optimizations? A vector is basically a raw array with optimizations.

Quote:I also wrote this class as a learning experience. I find that writing my own class helps me understand things better.


That's ok. Just don't use it for production code.
I use optimizations for the release version. Using iterators with vectors is as fast as a normal array it just requires more code to use it. Would it be a good idea to write a wrapper class that handles all the iterators to vectors to increase performance?

I did a lot of testing with vectors when I was writing my particle system and I found that they were just too slow, even when using iterators and pointers to each memory block.

What would you suggest I do?
Are you using MSVC? If so then it could be that your release code still has the security checks in it.
I am, maybe that is the cause of the problems.
Your version has n^2 insert performance.

This topic is closed to new replies.

Advertisement