I tried to create a list container with similar access of elements in c++ as in C#
I'm totally lost now because my main method first printed weird numbers.
The RList class should be like:
RList<ClassName or Primitive> VariableName;
VariableName.AddData(Class or Primitive);
VariableName[IndexOfElement] get the element
VariableName.RemoveAt(IndexOfElement) remove element
Can you tell me where I went totally wrong?
int main()
{
RList<int> Numbers;
Numbers.AddData(5);
Numbers.AddData(100);
Numbers.AddData(1500);
for (unsigned int x = 0; x < Numbers.GetLength(); x++)
{
cout << Numbers[0] << endl;
}
cin.get();
return 0;
}
Here is the Header file. I read that you have to put everything in header if you work with template.
#ifndef RList_H
#define RList_H
#include <new>
template <class T> class RList
{
private:
unsigned int m_Length;
T* ListObject;
void AllocateNew(T obj);
void RemoveIndex(unsigned int N);
public:
RList();
~RList();
void AddData(T obj);
void RemoveAt(unsigned int N);
unsigned int GetLength() { return m_Length; }
T operator[](unsigned int N){if (N < m_Length && N >= 0) {return (ListObject[N]);} return NULL; }
};
template <class T>
RList<T>::RList()
{
this->m_Length = 0;
}
template <class T>
RList<T>::~RList()
{
delete[] this->ListObject;
}
template <class T>
void RList<T>::AddData(T obj)
{
this->AllocateNew(obj);
this->m_Length++;
}
template <class T>
void RList<T>::RemoveAt(unsigned int N)
{
if( N < this->m_Length && N >= 0)
{
if ((this->m_Length - 1) > 0)
{
this->RemoveIndex(N);
this->m_Length--;
}
else
{
throw "Can't erase last index!";
}
}
}
template <class T>
void RList<T>::AllocateNew(T obj)
{
if (this->m_Length == 0)
{
this->ListObject[0] = obj;
}
else
{
T* NewListObject = new T [this->m_Length + 1];
for (unsigned int x = 0; x < this->m_Length; x++)
{
NewListObject[x] = this->ListObject[x];
}
NewListObject[this->m_Length] = obj;
delete [] ListObject;
this->ListObject = NewListObject;
delete [] NewListObject;
}
}
template <class T>
void RList<T>::RemoveIndex(unsigned int N)
{
T* NewListObject = new T [this->m_Length - 1];
for (int x = 0; x < this->m_Length -1; x++)
{
if (x != N)
{
NewListObject[x] = this->ListObject[x];
}
}
delete [] ListObject;
this->ListObject = NewListObject;
}
#endif // RList_H
Lots of problems:
Constructors should initialize all members
Rule of three not implemented (on owned pointers).
Horrible spacing (you need to format that code better).
All your array memory allocation is wrong.
Allocate:
template <class T>
void RList<T>::AllocateNew(T obj)
{
if (this->m_Length == 0)
{
// This will not work as you have not allocated the area for ListObjects.
// I don't think this is a special case. You should have allocated a zero
// length array in the constructor then then else part would have worked
// like normal when adding the first element.
this->ListObject[0] = obj;
}
else
{
// OK good start
T* NewListObject = new T [this->m_Length + 1];
// Rather than do this manually there is std::copy
for (unsigned int x = 0; x < this->m_Length; x++)
{
NewListObject[x] = this->ListObject[x];
}
NewListObject[this->m_Length] = obj;
// Though unlikely there is a posability of an exception from a destructor.
// So rather than call delete on a member you should swap the member and the
// temporary. Then when the object is a good state you can delete the old one.
delete [] ListObject;
this->ListObject = NewListObject;
// Definately do NOT do this.
// as you have just stored this pointer into ListObject.
// ListObject is now pointing at free'ed memory.
delete [] NewListObject;
// So I would have done (for the last section
// std::swap(this->ListObject, NewListObject);
// ++this->m_Length;
// // now we delete the old data
// delete [] NewListObject; // (remember we swapped above)
}
}
RemoveIndex
template <class T>
void RList<T>::RemoveIndex(unsigned int N)
{
T* NewListObject = new T [this->m_Length - 1];
for (int x = 0; x < this->m_Length -1; x++)
{
if (x != N)
{
// You need to compensate for the fact that you removed one
// element (otherwise you have a hole in your new array).
NewListObject[x] = this->ListObject[x];
}
}
// Same comment as above.
// Do not call delete on a member.
// Make sure the object is a good state before doing dangerous stuff.
delete [] ListObject;
this->ListObject = NewListObject;
}
if (this->m_Length == 0)
{
this->ListObject[0] = obj;
}
You have to allocate ListObject before you can do this.
Note: there are many problems with your implementation, you should post it to codereview, or check a book to see how to implement a proper vector.
You've got a lot of problems, but this one will surely crash your program:
(at the end of AllocateNew):
this->ListObject = NewListObject;
delete [] NewListObject;
Now, this->ListObject is pointing to memory that's been freed.
Can you tell me where I went totally wrong?
You're reinventing the STL vector class. You can write a thin-wrapper around it to provide the API you want, but it's probably easier to use the the class as-is. Your example would look like this:
#include <iostream>
#include <vector>
using namespace std;
int main( )
{
vector< int > Numbers;
Numbers.push_back( 5 );
Numbers.push_back( 100 );
Numbers.push_back( 1500 );
for ( unsigned int x = 0; x < Numbers.size( ); x++ )
{
cout << Numbers[x] << endl;
}
cin.get();
return 0;
}
Related
i have this reSize function in my Array header
void reSize(int newsize) {
T* old = items;
size = newsize;
items = new T[newsize];
for (int i = 0;i < length;i++)
items[i] = old[i];
delete[]old;
}
and my main code:
struct User{
string name;
Array<int> data;
};
int main() {
Array<User> x(3);
x.get(0).name = "Kmal";
x.get(0).data.push_back(2); x.get(0).data.push_back(3);
x.reSize(10);
cout << x.get(0).data.get(0) <<endl;
return 0;
}
the problem is after resizing, my values that were stored in "data" variable are gone.
when i commented the code.
//delete[] old
in the reSize function
it worked fine...so i guess the problem is when i delete the pointer it deletes also the pointer inside the struct object which i don't want it to happen..
i don't want to comment the command becuz a leak in the memory will happen...how to fix this problem ?.
Update: My Array Class .
#include <iostream>
using namespace std;
template <class T>
class Array {
private :
T* items;
int size;
int length;
public :
Array() {
this->size = 0;
items = new T[this->size];
length = 0;
}
Array(int size) {
this->size = size;
items = new T[this->size];
length = 0;
}
int getsize() {
return this->size;
}
template <class T> void push_back(T x) {
if ((length+1) <= size) {
items[length] = x;
length++;
}
else {
this->reSize(size+1);
items[length] = x;
length++;
}
}
template <class T> void Insert(int index, T x) {
if (length + 1 <= size) {
for (int i = length;i > index;i--) {
items[i] = items[i - 1];
}
items[index] = x;
length++;
}
else {
this->reSize(size+1);
for (int i = length;i > index;i--) {
items[i] = items[i - 1];
}
items[length] = x;
length++;
}
}
template <class T> int Find(T x) {
int index = -1;
for (int i = 0;i < length;i++) {
if (items[i] ==x) {
index = i;
break;
}
}
return index;
}
void remove(int index) {
items[index] = "";
if(index+1 < length)
for (int i = index;i < length-1;i++) {
items[i] = items[i + 1];
items[i + 1] = "";
}
length--;
}
void reSize(int newsize) {
T* old = items;
size = newsize;
items = new T[newsize];
for (int i = 0;i < length;i++)
items[i] = old[i];
delete[]old;
}
void Merge(Array<T> x){
T* old = items; int oldlength = length;
items = new T[size + x.size];
size = size + x.size;
length += x.length;
for (int i = 0;i < length;i++) {
if(i< oldlength)
items[i] = old[i];
else
items[i] = x.items[i-oldlength];
}
delete[] old;
}
T& get(int index) {
return items[index];
}
}
struct User{
string name;
Array<int> data;
};
int main() {
Array<User> x(3);
// this line causes some problems
x.get(0).name = "Kmal";
x.get(0).data.push_back(2); x.get(0).data.push_back(3);
x.reSize(10);
cout << x.get(0).data.get(0) <<endl;
return 0;
}
In your code, declaring Array<User> x(3) declares an empty array with 3 elements that are preallocated. The length property of the array is 0. When the array is copied, length(0) elements are copied over into the resized storage. When you access the 0th element, it won't be copied on resize. What you actually need to do is call push_back() to add an element to the array so that length becomes 1 and the element is copied on resize.
Also, your array class is lacking a proper copy constructor and move constructor, which means copying it won't work at all. This means that User cannot be copied properly since it contains an array, which means that resizing an array of User won't work. You need to implement a copy constructor and copy assignment operator to be able to copy the array. You also need a destructor since, right now, the array is leaking memory when it goes out of scope.
I am in a data structures course right now and I am designing my own array class for use in a project. While testing my methods, the program kept giving me garbage when I attempt to return values. After using visual studio's debugger, I managed to narrow the problem down to the resize function and more specificly the resizeArray. No matter what I enter for its size, it only has one entry and I can't figure out why. I've attempted using flat values as well as the dynamic ones I would be using in the final version.
This is the class I've been writing.
#include "ArrayClass.h";
#include <iostream>
using namespace std;
template <class T>
ArrayClass<T>::ArrayClass() {
thisArray = new T[1];
length = 1;
}
template <class T>
ArrayClass<T>::ArrayClass(T element) {
thisArray = new T[1];
thisArray[0] = element;
length = 1;
currentLastElement = 0;
}
template <class T>
ArrayClass<T>::ArrayClass(T element, int x) {
thisArray = new T[x];
thisArray[0] = element;
length = x;
currentLastElement = 0;
}
template <class T>
void ArrayClass<T>::addElement(T element) {
if (currentLastElement >= (length - 1)) {
resize(length);
length++;
thisArray[currentLastElement + 1] = element;
cout << thisArray[currentLastElement + 1];
currentLastElement += 1;
}
else {
thisArray[currentLastElement + 1] = element;
currentLastElement += 1;
}
}
template <class T>
void ArrayClass<T>::addElement(T element, int x) {
T tempElement;
if (x == currentLastElement + 1) {
this.addElement(element);
}
else {
tempElement = *thisArray[x];
thisArray[x] = element;
addElement(tempElement, x + 1);
}
}
template <class T>
void ArrayClass<T>::removeElement(int x) {
delete[x] thisArray;
for (int i = 0; i < currentLastElement; i++) {
cout << thisArray[1];
thisArray[x] = thisArray[x + 1];
x++;
}
}
template <class T>
T ArrayClass<T>::accessElement(int x) {
return thisArray[x];
}
template <class T>
void ArrayClass<T>::resize(int x) {
T * resizeArray;
resizeArray = new T[x];
for(int i = 0; i < length; i++) resizeArray[i] = thisArray[i];
thisArray = resizeArray;
};
This is what I've been using to test it.
#include <iostream>
#include "ArrayClass.cpp"
using namespace std;
int main() {
ArrayClass<int> intArray(1);
intArray.addElement(5);
cout << intArray.accessElement(0);
cout << intArray.accessElement(1);
intArray.removeElement(0);
cout << intArray.accessElement(0);
return 0;
}
In ArrayClass<T>::addElement(T element), you're calling resize as
resize(length);
which doesn't extends the array. You need
resize(length + 1);
BTW1: You need to delete[] the original array in resize, otherwise it'll be memory leak. Such as,
template <class T>
void ArrayClass<T>::resize(int x) {
...
delete[] thisArray;
thisArray = resizeArray;
};
BTW2: this.addElement(element); and delete[x] thisArray; won't compile.
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.
I have written a class Stack whose both sides are used, i.e. two stacks in one.
One from [0] until [someplace - 1] and one from [capacity-1] until [someplace +1].
Everything is fine but I have some problems with doubling the memory when my array is full.
My code works for doubling at first, but when it needs to double some more it gives me some weird error.
_ctrlvalidHeappointer
critical section error
This is my code. There is some explanation in the code too. When I push too many element in the stack it fails.
string firstname = "asasasasasaasasasasassasasasaasas";
string secondname= "asasdasfregeasasasasasgergergererg";
for (int i = 0; i < firstname.length(); i++)
{
a.push_at_first(firstname.at(i));
}
for (int i = 0; i < secondname.length(); i++)
{
a.push_from_end(secondname.at(i));
}
It is my class
using namespace std;
template <class T>
class Stack{
public:
Stack();
~Stack();
Stack(const Stack<T>& ob);
void double_size();
void push_at_first(T mydata);
void push_from_end(T mydata);
T & operator = (Stack<T> ob);
private:
int top;
int top2;
T * stack;
int capacity;
};
template <class T>
T& Stack<T>::operator = (Stack<T> ob)
{
if(capacity == ob.capacity){
top = ob.top;
top2 = ob.top2;
for (int i = 0; i < capacity; i++)
{
stack[i] = ob.stack[i];
}
return *this;}
else
{
capacity = ob.capacity;
stack = new T[capacity];
for (int i = 0; i < capacity; i++)
{
stack[i] = ob.stack[i];
}
}
}
template <class T>
Stack<T>::Stack (const Stack<T>& ob) :capacity(ob.capacity)
{
stack = new T[capacity];
top = ob.top;
top2=ob.top2;
for (int i = 0; i < capacity; i++)
{
stack[i] = ob.stack[i];
}
}
template <class T>
Stack<T>::~Stack()
{
delete [] stack;
}
template <class T>
Stack<T>::Stack()
{
capacity = 17;
top = 0;
top2 = capacity-1;
stack = new T[capacity];
}
template <class T>
void Stack<T>::push_at_first(T mydata)
{
if ( (top + 1) == (top2 -1) ) // 1 : because I want to Be a Empty Space between Two Stack so i can tell the difference
double_size();
stack[++top] = mydata;
}
template <class T>
void Stack<T>::push_from_end(T mydata)
{
if( (top + 1) == (top2 -1) ) // 1 : because I want to Be a Empty Space between Two Stack so i can tell the difference
double_size();
stack[--top2] = mydata;
}
template <class T>
void Stack<T>::double_size()
{
Stack<T> temp(*this);
capacity *= 2;
stack = new T[capacity];
top = temp.top;
top2 = capacity - (temp.capacity - temp.top2);// capacity - number of data in stack of temp ;
// if we have something in first stack then copy 0 to top elements of temp.stack to stack
if(top > 0)
{
for (int i = 0; i <= top ; i++)
{
stack[i] = temp.stack[i];
}
}
// There is Something Wrong Down here ! i can't figure out what !
if(top2 < capacity - 1)
{
for (int i = capacity-1; i >= top2; i--)
{
stack[i] = temp.stack[i-(temp.capacity)];
}
}
}
I see several problems.
You're missing a copy constructor and assignment operator.
You're explicitly calling the destructors of the elements.
This will lead to trouble when delete does it again, as it does automatically.
You're not allocating the proper amount of memory for temp.stack in double_size. Even though you have access to the private members of temp, you should let it manage itself (see copy constructor above).
(BTW: that variable is unnecessary - just copy from your old memory block to a new one, then delete the old block and assign the new block pointer to stack.)
There may also be some problems with the indexing in double_size, but you should fix those three problems first.
I wrote a template class and it works - but for some reason there is a problem with my dynamic allocation. initial length of arrays: old 2 new 4. the first time it works(old point on new(so now his size 4) and now, new is in the size of 8) but on the next round - it blows up on the delete [] temp; with heap problem. any ideas? thanks
template <class T>
void Log<T>::Add(T item)
{
// If array is full
if(m_oldSize == m_oldCount)
{
// prepare array switch
T* temp = m_old;
// Point to new array
m_old = m_new;
m_oldSize = m_newSize;
m_newSize *= ARRAY_MUL;
m_newCount = DEFAULT_COUNT;
//delete old
delete [] temp;
temp = NULL;
//create new array
m_new = new T[m_newSize];
}
// Add item and update new array
m_old[m_oldCount++] = item;
if(m_oldCount > FIRST_ROUND)
{
m_new[m_newCount++]= m_old[m_newCount];
m_new[m_newCount++]= m_old[m_newCount];
}
}
As this is homework I have just created a non elegant solution, you should be able to find the pitfalls and extend it.
#include <iostream>
using namespace std;
struct foo
{
foo(int h) : g(h) { }
int g;
};
template <typename T>
class bar
{
public:
bar() : curSize(2), curNo(0)
{
a = new T[curSize];
}
void Add(T item)
{
if (curNo == curSize) {
curSize = 2 * curSize;
T *newArray = new T[2*curSize];
for (size_t i = 0 ; i != curNo; ++i) {
newArray[i] = a[i];
}
delete[] a;
a = newArray;
}
a[curNo] = item;
++curNo;
}
void print()
{
for (size_t i = 0 ; i != curNo; ++i) {
cout << a[i]->g << endl;
}
}
private:
size_t curSize;
size_t curNo;
T * a;
};
int main()
{
foo *f1 = new foo(1);
foo *f2 = new foo(2);
foo *f3 = new foo(3);
foo *f4 = new foo(4);
bar<foo*> *g = new bar<foo*>();
g->Add(f1);
g->Add(f2);
g->Add(f3);
g->Add(f4);
g->print();
cout << "Add more and print" << endl;
g->Add(f1);
g->Add(f2);
g->Add(f3);
g->Add(f4);
g->Add(f3);
g->Add(f4);
g->print();
}