I'm having problem understanding where my memory leak is located in my project.
The template I have built looks like this:
#pragma once
#include "IHeap.h"
#include <iostream>
using namespace std;
template <typename T>
class dHeap
{
public:
dHeap(T size);
dHeap(T size, int nr);
dHeap(const dHeap &original);
~dHeap();
dHeap<T>& operator=(const dHeap<T> &original);
void deepCopy(const dHeap &original);
void push(const T &item);
T pop();
T peek()const;
int size()const;
int getdValue()const;
void printAll()const;
void heapify(int arr[], int size, int root);
void heapSort(int arr[], int size);
private:
//T nr;
T *arrHeap;
T nrOfItems;
T capacity;
T dValue;
void expandHeap();
};
template<typename T>
inline dHeap<T>::dHeap(T size)
{
capacity = size;
arrHeap = new T[capacity + 1];
nrOfItems = 0;
dValue = size;
}
template<typename T>
inline dHeap<T>::dHeap(T size, int nr)
{
capacity = size;
arrHeap = new T[nr];
nrOfItems = 0;
dValue = size;
}
template<typename T>
inline dHeap<T>::dHeap(const dHeap &original)
{
this->deepCopy(original);
}
template<typename T>
inline dHeap<T>::~dHeap()
{
delete[] arrHeap;
}
template<typename T>
inline dHeap<T>& dHeap<T>::operator=(const dHeap<T>& original)
{
if (this != &original)
{
this->deepCopy(original);
}
return *this;
}
template<typename T>
inline void dHeap<T>::expandHeap()
{
capacity *= 2;
T *temp = new T[capacity];
for (int i = 0; i < nrOfItems; i++)
{
temp[i] = arrHeap[i];
}
delete[] arrHeap;
arrHeap = temp;
}
template<typename T>
inline void dHeap<T>::deepCopy(const dHeap &original)
{
capacity = original.capacity;
nrOfItems = original.nrOfItems;
arrHeap = new T[capacity];
dValue = original.dValue;
for (int i = 0; i < original.nrOfItems; i++)
{
this->arrHeap[i] = original.arrHeap[i];
}
}
template<typename T>
inline void dHeap<T>::push(const T &item)
{
if (nrOfItems >= capacity)
{
expandHeap();
}
arrHeap[nrOfItems] = item;
nrOfItems++;
}
template<typename T>
inline T dHeap<T>::pop()
{
int removed = arrHeap[0];
arrHeap[0] = arrHeap[nrOfItems - 1];
nrOfItems--;
return removed;
}
template<typename T>
inline T dHeap<T>::peek() const
{
return arrHeap[0];
}
template<typename T>
inline int dHeap<T>::size() const
{
return this->nrOfItems;
}
template<typename T>
inline int dHeap<T>::getdValue() const
{
return this->dValue;
}
template<typename T>
inline void dHeap<T>::printAll() const
{
for (int i = 0; i < nrOfItems; i++)
{
cout << "Heap element " << i << ". " << arrHeap[i] << endl;
}
}
template<typename T>
inline void dHeap<T>::heapSort(int arr[], int size)
{
for (int j = 0; j < size; j++)
{
// Build heap - which means rearrange array
for (int i = size / 2 - 1; i >= 0; i--)
{
heapify(arrHeap, size, i);
}
for (int i = size - 1; i >= 0; i--)
{
swap(arrHeap[0], arrHeap[i]);
heapify(arrHeap, i, 0);
}
//when re-structured heap, use pop and re-do it again until done
arr[j] = pop();
}
}
template<typename T>
inline void dHeap<T>::heapify(int arr[], int n, int root)
{
int largest = root;
int leftChild = 2 * root + 1;
int rightChild = 2 * root + 2;
// If left child is larger than root
if (leftChild < n && arr[leftChild] > arr[largest])
{
largest = leftChild;
}
// If right child is larger than largest so far
if (rightChild < n && arr[rightChild] > arr[largest])
{
largest = rightChild;
}
// If largest is not root, heapify recursivly until done
if (largest != root)
{
swap(arr[root], arr[largest]);
heapify(arr, n, largest);
}
}
I have a pointer called heapArr which I use to build up a heap. When the program terminates the destructor is called and there have I put a delete[] this->heapArr declaration to remove the pointer when program is done.
And I have also added a delete[] this->heapArr in the expand function in order to free the memory before allocation the new expanded array.
I'm not sure I explained this perfectly but the problem is that I seem to miss to remove something because I get a memory leak warning when I end the program.
What have I missed?
Memory leaks in deepCopy, where you allocate new memory without de-allocating the old.
That being said, don't allocate memory yourself. A good chunk of your code is duplicating the functionality of std::vector, so use std::vector<T> instead of T*.
(If for some reason you cannot use std::vector I would recommend you implement a replacement. Divide-and-conquer by splitting memory management from the heap logic.)
Related
I tried to make a dynamic array that adds elements at the beginning of the array. It works just fine with int, but when i try double, it gives me the error Process returned -1073741819 (0xC0000005). Debugging it works perfectly and all are in range, but when i run it crashes.
This is the header:
#define DYNAMICARRAY_H
#include <cstddef>
template <class T>
class DynamicArray
{
public:
DynamicArray();
DynamicArray(size_t);
DynamicArray(const DynamicArray&);
virtual ~DynamicArray();
DynamicArray& operator=(const DynamicArray&);
T &operator[] (size_t);
void add(T element);
size_t getCapacity();
size_t getLength();
bool isEmpty();
void print();
void resizeArr();
protected:
private:
T *arr;
size_t capacity;
size_t length;
};
#endif // DYNAMICARRAY_H
This is the .cpp
#include "DynamicArray.h"
#include <iostream>
template <class T>
DynamicArray<T>::DynamicArray()
{
length = 0;
capacity = 1;
arr = (T*)malloc(capacity * sizeof(arr));
if(!arr){
throw std::bad_alloc();
}
}
template <class T>
DynamicArray<T>::DynamicArray(size_t newSize)
{
length = 0;
capacity = newSize;
arr = (T*)malloc(capacity * sizeof(arr));
if(!arr){
throw std::bad_alloc();
}
}
template <class T>
DynamicArray<T>::~DynamicArray()
{
delete[] arr;
delete arr;
delete &capacity;
delete &length;
}
template <class T>
DynamicArray<T>::DynamicArray(const DynamicArray& other)
{
length = other.length;
capacity = other.capacity;
arr = (T*)malloc(capacity * sizeof(arr));
if(!arr){
throw std::bad_alloc();
}
for(size_t i = 0; i < length; i++){
arr[i] = other.arr[i];
}
}
template <class T>
DynamicArray<T>& DynamicArray<T>::operator=(const DynamicArray& rhs)
{
if (this == &rhs){
return *this;
}
delete[] arr;
length = rhs.length;
capacity = rhs.capacity;
arr = (T*)malloc(capacity * sizeof(arr));
if(!arr){
throw std::bad_alloc();
}
for(size_t i = 0; i < length; i++){
arr[i] = rhs.arr[i];
}
return *this;
}
template <class T>
size_t DynamicArray<T>::getLength()
{
return length;
}
template <class T>
size_t DynamicArray<T>::getCapacity()
{
return capacity;
}
template <class T>
bool DynamicArray<T>::isEmpty(){
return length == 0;
}
template <class T>
T &DynamicArray<T>::operator[] (size_t index)
{
if(index >= length){
std::cout << "Array index out of bounds" << "\n";
exit(0);
}
return arr[index];
}
template <class T>
void DynamicArray<T>::add(T element)
{
if(length >= capacity){
resizeArr();
}
if(!isEmpty()){
for(size_t i = length; i > 0; i--){
arr[i] = arr[i-1];
}
}
arr[0] = element;
length ++;
}
template <class T>
void DynamicArray<T>::print()
{
if(length == 0){
std::cout << "The array is empty!";
}
else{
for(size_t i = 0; i < length; i++){
std::cout << arr[i] << " ";
}
}
std::cout << "\n";
}
template <class T>
void DynamicArray<T>::resizeArr(){
size_t newCapacity = capacity * 2;
T *arr2 = (T*)realloc(arr, newCapacity * sizeof(arr));
if(!arr2){
std::cout << "Bad memory allocation";
throw std::bad_alloc();
}
arr = arr2;
capacity = newCapacity;
}
template class DynamicArray<double>;
template class DynamicArray<int>;
And the main
#include "DynamicArray.h"
#include <cstdlib>
#include <time.h>
#include <cstddef>
using namespace std;
int main()
{
srand (time(NULL));
DynamicArray<int> d(5);
int randomInt;
for(size_t i = 0; i < d.getCapacity(); i++){
randomInt = rand()% 100;
d.add(randomInt);
}
d.print();
d.add(5);
d.add(55);
d.add(3);
d.add(33);
d.add(37);
d.print();
delete &d;
cout << "\n\n";
DynamicArray<double> d2(5);
double randomDouble;
for(size_t i = 0; i < d2.getCapacity() - 3; i++){
//randomDouble = (double)rand() / ((double)RAND_MAX);
randomDouble = 0.5f;
d2.add(randomDouble);
d2.print();
}
d2.print();
return 0;
}
It crashes at the second for in the main, I've tried to make sure everything it set correctly, but still won't work:
for(size_t i = 0; i < d2.getCapacity() - 3; i++){
//randomDouble = (double)rand() / ((double)RAND_MAX);
randomDouble = 0.5f;
d2.add(randomDouble);
d2.print();
}
arr = (T*)malloc(capacity * sizeof(arr));
delete[] arr;
delete arr;
delete &capacity;
delete &length;
delete &d;
You pass pointers to delete[] and delete that were not returned from new[] or new respectively. Behaviour of the program is undefined. Relevant language rule:
[expr.delete]
... In a single-object delete expression, the value of the operand of delete may be a null pointer value, a pointer to a non-array object created by a previous new-expression, or a pointer to a subobject representing a base class of such an object. If not, the behavior is undefined. In an array delete expression, the value of the operand of delete may be a null pointer value or a pointer value that resulted from a previous array new-expression.
If not, the behavior is undefined. ...
Every delete expression of your program violate this rule.
To fix this, you must consistently use free on memory allocated with malloc, realloc or strdup, and use delete with pointers allocated with new, delete[] with pointers allocated with new[], absolutely no deallocation functions with pointers to non-dynamic objects such as member variables or objects with automatic or static storage duration, (or invalid pointers).
arr = (T*)malloc(capacity * sizeof(arr));
sizeof(arr) is the same as sizeof(T*) which isn't what you want, I suppose.
This should rather be sizeof(*arr) or sizeof(T).
Apart from that, don't mix malloc/delete or new/free, as others already pointed out.
If you're doing C, use malloc/free, and if you're in C++ use new/delete.
Using new would change the above to
arr = new T[capacity];
avoiding the whole sizing altogether.
In advanced, let me thank your for looking at this code for me, because it has been bugging me for a while now and I can't seem to find the issue.
Whenever I run it, it doesn't throw any errors within the console, instead it throws this error:
Debug Assertion Failed!
Program: [Filepath to .exe]
File: minkernel\crts\ucrt\src\appcrt\heap\debug_heap.cpp
Line 892
Expression: is_block_type_valid(header->_block_use)
I've been trying to figure it out, but it just wont work for me. I believe it has something to do with the template types I am passing in, as it only crashes whenever I try to initialize a minHeap object or try my Push method, which I also believe is an issue.
Once again, thank you all so much for looking at my code.
Main:
#include "minHeap.h"
#include "Node.h"
#include <iostream>
using namespace std;
int main() {
Node<char> A = Node<char>(0, 'A');
Node<char> B = Node<char>(1, 'B');
Node<char> C = Node<char>(2, 'C');
Node<char> D = Node<char>(3, 'D');
minHeap<char> myHeap = minHeap<char>();
//Below doesn't work, something about subscript is not of integrap type
//myHeap.push(A.index, A.value);
//myHeap.push(B.index, B.value);
//myHeap.push(C.index, C.value);
//myHeap.push(D.index, D.value);
cout << A.index << endl;
myHeap.~minHeap();
return 0;
}
Here is Node.h:
#pragma once
template<typename T>
class Node
{
public:
float index;
T value;
Node(float indx, T val);
~Node();
};
template<typename T>
inline Node<T>::Node(float indx, T val)
{
index = indx;
value = val;
}
template<typename T>
inline Node<T>::~Node()
{
}
And finally, minHeap:
#pragma once
template<typename T>
class minHeap
{
private:
T* arr[100];
int arrSize = 0;
void heapifyUp(int indx);
void heapifyDown(int indx);
int getParent(int indx);
int childLeft(int indx);
int childRight(int indx);
int swap(int indxA, int indxB);
public:
minHeap();
~minHeap();
void push(int indx, T val);
void pop();
};
template<typename T>
inline minHeap<T>::minHeap()
{
}
template<typename T>
inline minHeap<T>::~minHeap()
{
delete[] arr;
}
template<typename T>
inline void minHeap<T>::heapifyUp(int indx)
{
if (indx <= 0) return;
int j = getParent(indx);
if (arr[indx] < arr[j]) {
int temp = arr[indx];
arr[indx] = arr[j];
arr[j] = temp;
}
heapifyUp(j);
}
template<typename T>
inline void minHeap<T>::heapifyDown(int indx)
{
int j;
//if no left child
if (childLeft(indx) > arrSize - 1) return;
//if no right child
if (childRight(indx) > arrSize - 1) j = childLeft(indx);
//No children
else j = (arr[childLeft(indx)] < arr[childRight(indx)]) ? (childLeft(indx)):(childRight(indx));
if (arr[indx] > arr[indx]) {
int temp = arr[indx];
arr[indx] = arr[j];
arr[j] = temp;
}
heapifyDown(j);
}
template<typename T>
inline int minHeap<T>::getParent(int indx)
{
return (indx - 1) / 2;
}
template<typename T>
inline int minHeap<T>::childLeft(int indx)
{
return 2 * i + 1;
}
template<typename T>
inline int minHeap<T>::childRight(int indx)
{
return 2 * i + 2;
}
template<typename T>
inline int minHeap<T>::swap(int indxA, int indxB)
{
int tempA = arr[indxA];
int tempB = arr[indxB];
arr[indxA] = tempB;
arr[indxB] = tempA;
return 0;
}
template<typename T>
inline void minHeap<T>::push(int indx, T val)
{
//Something with Array is broken. Fix it pupper
int tempVal = arr[indx];
arr[indx] = val;
arrSize += 1;
heapifyUp(arrSize - 1);
}
template<typename T>
inline void minHeap<T>::pop()
{
int temp = arr[0];
arr[0] = arr[arrSize - 1];
arr[arrSize - 1] = nullptr;
arrSize -= 1;
heapifyDown(0);
}
Why are you calling myHeap.~minHeap();? This results in myHeap being destroyed twice, with the second call trying to free memory that has already been freed. This can cause the error you're seeing.
You can construct your variables a lot more concisely:
Node<char> A(0, 'A');
minHeap<char> myHeap;
I have been looking through the std::vectors source code and looking at how it's capacity (vector.capacity()) function works, i'm not quite understanding how i would implement it into my Dynamic array source code. I would not just be returning the current container size would i. e.g dynarray.size().
,Thanks
#include <iostream>
#include <vector>
#include <iterator>
#pragma once
template<typename T>
class DynamicArrayIter
{
public:
DynamicArrayIter(T* data) : newData(data) { }
//DynamicArrayIter(const DynamicArrayIter& o); // Copy constructor
//DynamicArrayIter& operator=(const DynamicArrayIter& o); // Assignment operator
DynamicArrayIter operator++() { DynamicArrayIter i = *this;newData++; return i;}
DynamicArrayIter operator++(int junk) {newData++;return *this; }
T& operator*() {return *newData; }
bool operator==(const DynamicArrayIter& rhs) {return newData == rhs.newData; }
bool operator!=(const DynamicArrayIter& rhs) { return newData != rhs.newData;}
DynamicArrayIter<T> operator+(int _i)
{
DynamicArrayIter<T> iter = *this;
for (int i = 0; i < _i; ++i)
{
if (iter.newData) //If there's something to move onto...
++iter;
else
break;
}
return iter; //Return regardless of whether its valid...
}
private:
T* newData;
};
template<typename T>
class DynamicArray
{
public:
DynamicArray<T> operator=(const DynamicArray<T>&);//Dynamic Array equals Dynamic Array
DynamicArray();//Constructor
~DynamicArray();//Destructor
void push_back(const T&);//Push back a new element into the DynArray
void pop_back();//Pop an element off the back of the DynArray
void print();//Prints out what is in the container
bool empty();//Empty the DynArray container
void reserve(int);//Reserver a size of which the Dynarray can reach, once it reachers the limit it will increase etc.
void resize(int);//resize the Dynrray container data will be carried into the new size either cutting off eccess data or reserving space for more.
void swap(DynamicArray<T>);//Swap the contents in the Dynarray with another Dynarray containers.
void assign(size_t,T);//Assign new content to the Dynarray, replacing the current elements and changing its size accordingly
void assign(DynamicArrayIter<T>, DynamicArrayIter<T>);//Assign new content to the Dynarray, replacing the current elements and changing its size accordingly
void insert(DynamicArrayIter<T>,T);//Insert a element at a certain positon elements will be moved and adjusted accordingly
void erase(DynamicArrayIter<T>);//Erase an element at a certain postion
void erase(DynamicArrayIter<T>,DynamicArrayIter<T>);//Erase an element at a certain postion
T& at(int );// Element postion at index
T& front();//elements t postion
T& back();//elements back position
T& operator[] (int);//subscript location access
size_t capacity();//capacity of the container
size_t max_size();//max size of the vontainer
DynamicArrayIter<T> begin();//Begin on the container/DynArray - Iterator uses this to grab the begin of the Dynarray
DynamicArrayIter<T> end();//End on the container/DynArray - Iterator uses this to grab the End of the Dynarray
void clear();//Clear the whole container
int size();//Size of the current container returns sizeofarray
private:
T* myArray;//Where data is stored
int sizeofarray = 0;//size of the current container
};
template<typename T>
inline DynamicArray<T> DynamicArray<T>::operator=(const DynamicArray<T>&newDynArray)
{
myArray = new T[newDynArray.size()];
for (size_t i = 0; i < newDynArray.size(); i++)//will make the current array the size of the new one
{
myArray[i] = newDynArray.myArray[i];//Current Dynarray = the pass in Dynarray - Steps through changign each element
}
return newDynArray;//return the passed data
}
template<typename T>
inline DynamicArray<T>::DynamicArray()
{
myArray = new T[sizeofarray];//Creating a new Dynarray of size
}
template<typename T>
inline DynamicArray<T>::~DynamicArray()
{
delete[] myArray;//deleting the Dynarray
}
template<typename T>
inline void DynamicArray<T>::push_back(const T& pusheddata)
{
T *temp = myArray;//Creating a temp array with the value of the current Dynarray
myArray = new T[++sizeofarray];//Dynarray = new Dynarray of current size + 1 // Size is being incremented from this
myArray[sizeofarray - 1] = pusheddata;//Pushing the element onto the back of the Array
for (int i = 0; i < sizeofarray - 1; ++i)//It is sizearray - 1 as we dont the temp does not have the data we just pushed onto the back
{
myArray[i] = temp[i];//going through a loop putting the data from the temp we created back into the DynArray.
}
delete[] temp;//delete the temp
}
template<typename T>
inline void DynamicArray<T>::pop_back()
{
T *temp = myArray;//Creating a temp array with the value of the current Dynarray
myArray = new T[sizeofarray--];//Dynarray = new Dynarray of current size - 1 // Size is being decreased from this
for (int i = 0; i < sizeofarray; ++i)
{
myArray[i] = temp[i];//Dynarray equals the temp values
}
delete[] temp;//Delete the temp
}
template<typename T>
inline void DynamicArray<T>::print()
{
for (size_t i = 0; i < sizeofarray; i++)
{
std::cout << myArray[i] << std::endl;//Just looping through and printing the element until it hits size.
}
}
template<typename T>
inline bool DynamicArray<T>::empty()
{
if (size() == 0)
{
return true;//return true if size is 0
}
return false;//return flase if size >=1
}
template<typename T>
inline void DynamicArray<T>::reserve(int r_size)
{
sizeofarray = r_size;//size = the reserve size
}
template<typename T>
inline void DynamicArray<T>::resize(int newsize)
{
T *temp = myArray;//Creating a temp with the current Dynarray inside of it
myArray = new T[newsize];//Dynarray = a new Dynarray of size (newsize)
for (int i = 0; i < newsize; ++i)
{
myArray[i] = temp[i];//Setting the Dynarrays elements to the temps
}
for (int i = sizeofarray; i < newsize; i++)
{
myArray[i] = NULL;//Set the elements outside the size allowed to NULL
}
sizeofarray = newsize;//Size = new size
delete[] temp;//delete the temp
}
template<typename T>
inline void DynamicArray<T>::swap(DynamicArray<T> newSwap)
{
clear();//clear the current Dynarray
for (size_t i = 0; i < newSwap.sizeofarray; i++)
{
myArray[i] = newSwap.myArray[i];//Newly cleared Dynarray elements = passed in swapped data
sizeofarray++;//increment the size
}
}
template<typename T>
inline void DynamicArray<T>::assign(size_t n, T val)
{
clear();//Clear the Dynarray
myArray = new T[n];//Dynarray = new Dynarray of size_t n
for (size_t i = 0; i < n; i++)//for i < size_t n
{
myArray[i] = val;//Dynarray = val passed through
sizeofarray++;//increment the size of the Dynarray
}
}
template<typename T>
inline void DynamicArray<T>::assign(DynamicArrayIter<T> first, DynamicArrayIter<T> last)
{
int n = 0;//temp size holder
for (DynamicArrayIter<T> iter = first; iter != last; ++iter) {
n++;//increment the temp size holder
}
clear();//clear the Dynarray
myArray = new T[n];//Make a new Dynarray and its size is the temp size holders
for (DynamicArrayIter<T> newiter = first; newiter != last; ++newiter) {
myArray[sizeofarray] = *newiter;//Iterate through and set each element to the value passed in
sizeofarray++;//incremenet the size
}
}
template<typename T>
inline void DynamicArray<T>::insert(DynamicArrayIter<T> position, T val)
{
int sizeofthis = 0;//temp size holder for iter
int j = 0;//Index position // increments when position is meet
for (DynamicArrayIter<int> iter = begin(); iter != position; ++iter){
++sizeofthis;//increase the temp size holder fo riter
}
T *temp = myArray;//Create a new temp Dynarray
sizeofarray += 1;//temp size hodler + 1
myArray = new T[sizeofarray];//Dynarray = new Dynarray of temp size holder for iter
for (size_t i = 0; i < sizeofarray; i++)
{
if (i == sizeofthis)//if the for loops i = tempsize holders
{
myArray[sizeofthis] = val;//Dynarray element = val being passed in
j++;//Index pos ++
}
myArray[i + j] = temp[i];//Dynarray = Temps values // Will change when inserted pos is reached // dynamically chagne size
}
delete[] temp;//delete temp
}
template<typename T>
inline void DynamicArray<T>::erase(DynamicArrayIter<T> position)
{
int sizeofthis = 0;//temp size holder for iter
int j = 0;//index pos//increments wehn pos is met
for (DynamicArrayIter<int> iter = begin(); iter != position; ++iter) {
++sizeofthis;//increment the temp size holder
}
T *temp = myArray;//temp = current Dynarray
sizeofarray -= 1;//size decreased by 1
myArray = new T[sizeofarray];//new Dynarray of the new size
for (size_t i = 0; i < sizeofarray; i++)
{
if (i == sizeofthis)//if the loops i reaches the temp size holders value
{
myArray[sizeofthis] = myArray[sizeofthis + 1];//Dynarray at sizeoftihs = Dynarrays next element
j++;//index pos ++
}
myArray[i] = temp[i + j];//Dynarray = the temp[idexpos will be greater > 0 if i == sizeofthis]
}
delete[] temp;//delete the temp
}
template<typename T>
inline void DynamicArray<T>::erase(DynamicArrayIter<T> first, DynamicArrayIter<T> last)
{
int sizeofthis = 0;
for (DynamicArrayIter<int> iter = first; iter != last; ++iter) {
++sizeofthis;
}
T *temp = myArray;
sizeofarray = sizeofarray - sizeofthis - 1;
myArray = new T[sizeofarray];
for (size_t i = 0; i < sizeofarray; i++)
{
if (i < sizeofthis)
{
myArray[sizeofthis - 1 + i] =NULL;
}
myArray[i] = temp[i];
}
delete[] temp;
}
template<typename T>
inline T & DynamicArray<T>::at(int place)
{
return myArray[place];//return the element at place
}
template<typename T>
inline T & DynamicArray<T>::front()
{
return myArray[0];//return the first element in the array
}
template<typename T>
inline T & DynamicArray<T>::back()
{
return myArray[sizeofarray];//return the last element in the array
}
template<typename T>
inline T & DynamicArray<T>::operator[](int place)
{
return myArray[place];//return the element at place using subscript operator instead of dynarray.at()
}
template<typename T>
inline size_t DynamicArray<T>::capacity()
{
return back() - front();//
}
template<typename T>
inline size_t DynamicArray<T>::max_size()
{
return std::numeric_limits<T>::max();
}
template<typename T>
inline DynamicArrayIter<T> DynamicArray<T>::begin()
{
return DynamicArrayIter<T>(myArray);
}
template<typename T>
inline DynamicArrayIter<T> DynamicArray<T>::end()
{
return DynamicArrayIter<T>(myArray + sizeofarray - 1);
}
template<typename T>
inline void DynamicArray<T>::clear()
{
sizeofarray = 0;
myArray = new T[sizeofarray];
myArray[0] = NULL;
}
template<typename T>
inline int DynamicArray<T>::size()
{
return sizeofarray;
}
size() returns the number of elements that are held by the container while capacity is how many elements it can hold before more space must be allocated. So capacity can be greater than the size of the vector.
In your implementation, you have to create one more member capacity that will store the actual size of allocated array whereas size will hold the number of elements the container is holding.
Disclaimer: Yes, I know about std::vector. I'm doing this for the sake of learning.
I'm working on making a dynamic array class, and I'm trying to get add to work.
template <class T>
void Array<T>::add(T value)
{
T * tmp = new T[mCount];
for (int i = 0; i < mCount; i++)
{
tmp[i] = mData[i];
}
mCount++;
delete[] mData;
mData = tmp;
mData[mCount - 1] = value;
}
It works... sort of. The function works in adding the element, but then the program crashes when exiting. No errors, no nothing. It just freezes, and I have to close it using (Shift + F5).
So, what's wrong with this?
Here's my whole class. If I didn't include a function it means there's no code in it.
#ifndef ARRAY_H
#define ARRAY_H
using namespace std;
template <class T>
class Array
{
private:
T * mData;
int mCount;
public:
Array();
~Array();
void add(T value);
void insert(T value, int index);
bool isEmpty();
void display();
bool remove(T value);
bool removeAt(int index);
int size();
T & operator[](const int index);
};
// Constructors / Destructors
// --------------------------------------------------------
template <class T>
Array<T>::Array()
{
mCount = 0;
mData = new T[mCount];
for (int i = 0; i < mCount; i++)
mData[i] = 0;
}
template <class T>
Array<T>::~Array()
{
delete[] mData;
}
// General Operations
// --------------------------------------------------------
template <class T>
void Array<T>::add(T value)
{
T * tmp = new T[mCount];
for (int i = 0; i < mCount; i++)
{
tmp[i] = mData[i];
}
mCount++;
delete[] mData;
mData = tmp;
mData[mCount - 1] = value;
}
template <class T>
void Array<T>::display()
{
if (isEmpty())
{
cout
<< "The array is empty."
<< "\n\n";
return;
}
cout << "(";
for (int i = 0; i < mCount; i++)
{
cout << mData[i];
if (i < mCount - 1)
cout << ", ";
}
cout << ")" << "\n\n";
}
template <class T>
bool Array<T>::isEmpty()
{
return mCount == 0;
}
template <class T>
int Array<T>::size()
{
return mCount;
}
// Operator Overloads
// --------------------------------------------------------
template <class T>
T & Array<T>::operator[](const int index)
{
return mData[index];
}
#endif
If you need any additional info lemme know and I can post it.
Assuming mCount keeps the number of elements in the array, then when adding a new element you really have to allocate at least mCount + 1 elements (assuming of course you want to keep all the old ones and the new one) via:
T * tmp = new T[mCount + 1];
as opposed to:
T * tmp = new T[mCount];
If it's for anything else other than educational purposes, please use std::vector instead. For example your add function is not exception safe.
So, I've defined template class and then i tried to overload some operators.
template <typename T> class Set
{
public:
Set(void);
Set(Set&);
~Set(void);
bool contains(T elem);
bool add(T elem);
bool remove(T elem);
bool add(T* tab, int size);
T* getSet();
int size();
Set<T> &operator+(Set<T> &snd);
Set<T> &operator-(Set<T> &snd);
private:
T *elements;
int numOfElem;
};
When I try to add element to the Set by add method everything works fine.
template<typename T>
bool Set<T>::add(T elem)
{
bool found = false;
for(int i =0; !found && i<numOfElem; i++){
if(elem == elements[i]) found = true;
}
if( !found ){
numOfElem++;
T* tmp = new T[numOfElem];
for(int i =0; i<numOfElem-1; i++){
tmp[i] = elements[i];
}
tmp[numOfElem-1] = elem;
delete[] elements;
elements = tmp;
}
return !found;
}
template<typename T>
bool Set<T>::add(T* myArray, int size)
{
bool result = false;
for(int i =0; i<size; i++){
add(myArray[i]);
}
return result;
}
template<typename T>
Set<T>& Set<T>::operator+(Set<T> &snd)
{
Set *temp = new Set(*this);
temp->add(snd.getSet(), snd.size());
return *temp;
}
template<typename T>
void Set<T>::operator=(Set<T> &snd)
{
numOfElem = snd.numOfElem;
elements = new T[numOfElem];
for(int i =0; i < numOfElem; i++){
elements[i] = snd.elements[i];
}
}
template<typename T>
int Set<T>::size()
{
return numOfElem;
}
template<typename T>
T* Set<T>::getSet()
{
return elements;
}
template<typename T>
Set<T>::Set()
{
numOfElem = 0;
elements = nullptr;
}
template<typename T>
Set<T>::Set(Set& old)
{
numOfElem = old.numOfElem;
elements = new T(numOfElem);
for(int i = 0; i< numOfElem; i++){
elements[i] = old.elements[i];
}
}
template<typename T>
Set<T>::~Set()
{
numOfElem = 0;
delete[] elements;
elements = nullptr;
}
But if I use + operator instead (adding two separate sets) the error occurs while trying to delete the array (15 Line). Any ideas?
int main(){
Set <char> set1, set2, set3;
char tab[] = {'a','d','f','g'} ;
set1.add(tab, 4);
char tab2[] = {'a','d','x','y','z'} ;
set2.add(tab2,5);
set3= set1+set2;
}
You have a mistake in your copy constructor:
elements = new T(numOfElem);
It should be
elements = new T[numOfElem];
By writing new T(numOfElem); you allocate only one variable with its value initialized to numOfEllem.
Use a std::vector instead of the array and you will avoid such problems.
Your code is also leaking a memory in the addition operator:
template<typename T>
Set<T>& Set<T>::operator+(Set<T> &snd)
{
Set *temp = new Set(*this);
temp->add(snd.getSet(), snd.size());
return *temp;
}
You are allocating a memory and you never delete it so if you call that function too often you program may run out of its virtual memory and will crash with the uncaught std::bad_alloc exception. Change the function to this:
template<typename T>
Set<T> Set<T>::operator+(Set<T> &snd)
{
Set temp(*this);
temp.add(snd.getSet(), snd.size());
return temp;
}