Resize array using new - c++

So I am trying to resize an array by making a function call ResizeArray(). However, I don't know what is the correct way to use "delete" in this case. (I make a new int * and copy the value from the original to it and then I make the original pointer points to the new one, now I don't know what to "delete"
class Base
{
private:
int sizeInClass;
int *arrayy=nullptr;
public:
Base(int s)
{
sizeInClass=s;
arrayy = new int[s]{};
setValue();
};
void setValue()
{
for(int x=0;x<sizeInClass;x++)
{
arrayy[x]=x;
}
}
void print()
{
int countter=0;
for(int x=0;x<sizeInClass;x++)
{
countter++;
cout<<arrayy[x]<<endl;
}
cout<<"The size of the array is : "<<countter<<endl;
}
void ResizeArray(int newSize)
{
int *newArray = nullptr;
newArray = new int[newSize];
for(int x=0;x<sizeInClass;x++)
{
newArray[x]=arrayy[x];
}
delete [] arrayy; /////////////////////////////////// should i use deleate here ?
arrayy = newArray;
delete [] newArray; /////////////////////////////////// or should I use deleate here ?
sizeInClass = newSize;
}
~Base()
{
delete [] arrayy; /////////////////////////////////// or just use delete here
arrayy=nullptr;
}
};
int main()
{
Base b(5);
b.print();
b.ResizeArray(8);
b.setValue();
b.print();
return 0;
}

The first and the 3rd of your suggested delete are correct.

Regarding handling resources,
for sure you need de-allocation in destructor, to free resources when your container class
is destroyed. When you want to resize contained array, you are handling it in ResizeArray function, so below is basic proposal for it, with clarification comments:
void ResizeArray(int newSize)
{
int *newArray = new int[newSize];
if (nullptr != newArray) { // we take action only if allocation was successful
for(int x=0;x<sizeInClass;x++)
{
newArray[x]=arrayy[x];
}
delete [] arrayy; // good, here you delete/free resources allocate previously for an old array
arrayy = newArray; // good, you redirect member ptr to newly allocated memory
/* delete [] newArray; ups, we have member ptr point to this location
and we cannot delete it, after this, accessing it would be UB,
beside in dtor we would have double, second deletion */
sizeInClass = newSize;
}
}
Your destructor is fine.
There could be further improvements in your code, but this is related to your question.

Related

c++ template<typename T> delete

I am playing around with my containers.
In my template class for an container i make a pointer of T* (T* mData;) as a member variable of the container class. This is a pointer to an array type.
In the destructor i call the delete keyword delete mData; or delete[] mData; but all i hear is a ding in the test application and no more output is write to the console.
Can someone please explain what is going on is deleting a member of T* mData; somehow different to deleting everything else? if so can someone please explain I've looked everywhere and can't find an answer.
UPDATE
I read the comments and since people were willing to help in return i have decided to post the this update and answer the question itself. Ps don't laugh it was a silly mistake.
OLD CODE (looked something like this)
template<typename T>
class TestVector {
// members
T* mData;
size_t mSize;
// methods
void AddData(T data){
T* buffer;
memcpy_s(buffer, sizeof(mData), mData, sizeof(mData));
if(!buffer){
// log error
return;
}
mSize++;
SafeDelete(mData); // deleting this here was the problem (check destructor)
mData = new T[mSize];
mData = buffer;
mData[mSize - 1] = data;
}
// constructors
TestVector(void){
mData = new T[0];
ZeroMemory(mData, sizeof(mData);
mSize = 0;
}
~TestVector(void){
SafeDelete(mData); // when deleting the mData member again here the problem would occur, the destructor was called the beep noise would sound and the console window would freeze
}
// operators
};
I will answer what i did to change this as a Answer to the question . . .
I will admit i do not understand why deleting the same pointer of the class more than once gave an error, maybe the memory address of the new pointer wasn't know to the class so the destructor couldn't find it but to solve the issue i went with old school C.
template<typename T>
class TestVector {
private:
T * mData;
size_t mSize = 0;
public:
TestVector(void) {
mSize = 2;
mData = (T*)malloc(mSize * sizeof(T));
for (int i = 0; i < mSize; i++) {
mData[i] = i;
}
cout << "Values in t1 are: " << mData[0] << ", " << mData[1] << endl;
}
~TestVector(void) {
free(mData); // only place the pointer is ever deleted
}
public:
void AddData(T data) {
mSize++;
T* newData = (T*)realloc(mData, mSize * sizeof(T));
mData = newData;
mData[mSize - 1] = data;
for (int i = 0; i < mSize; i++) {
cout << "Value: " << i << " is equal to: " << mData[i] << endl;
}
}
};
I just used malloc() to allocate, realloc() to reallocate a bigger array to the pointer and free() to release the pointer.
I could of just omitted the SafeDelete(mData); in the first version and just called new over the top i think but i actually prefer using old school C for this type of thing, it makes more sense :)

class destructor segmentation fault

WHy does this code cause segmentation fault?
It causes seg fault in destructor.
But when I call the free function without destructor, it's ok.
Some answers does not understand the problem.
The problem is that If I use the free function in the main()
s.free();
It works fine..
But I make the destructor do the free() job, it is not OK.
#include<iostream>
using namespace std;
class Stack
{
public:
int pop() {
data = next->data;
auto tmp = next;
next = next->next;
delete tmp;
return data;
}
void push(int n) {
Stack* p = new Stack();
p->data = n;
p->next = next;
next = p;
size++;
}
virtual ~Stack() {
free();
}
void free() {
while(next) pop();
}
Stack* next = nullptr;
protected:
int data;
int size = 0;
};
int main()
{
Stack s;
for(int i=0; i<30; i++) s.push(i);
}
Your pop function destroys the entire stack. It deletes the tmp node (by calling the Stack destructor), which still points to the new next.
And since the Stack destructor calls delete on next, you get a mess of multiple destructor calls on the same objects.
JMA beat me to it by a few seconds, so refer to their code fix for a quick solution.
However, I would recommend you add a dedicated Node struct instead of composing Stacks, it will actually increase the clarity of your code.
In the constructor of the class you must set next = nullptr, otherwhise the loop in the free() function won't stop.
Edit:
I think the problem is because on the pop you delete, and that calls the destructor again.
try this one:
`
int pop() {
data = next->data;
auto tmp = next;
next = next->next;
tmp->next = nullptr;
delete tmp;
return data;
}
`

Destructor of a class C with members of pointer C

Assume the following class declaration:
class NTree
{
private:
const T* fKey;
NTree<T, N>* fNodes[N]; // N subtrees of degree N
NTree();
...
}
in which we can add some fNodes, representing a subtree given an index. These will be dynamically allocated using new. However, there are elements which are static, and not dynamically allocated:
public:
static NTree<T, N> NIL; // sentinel
...
We choose to allocate this on the stack using the default constructor supplied above.
template<class T, int N>
NTree<T, N> NTree<T, N>::NIL;
Now, let's say we wish to delete an NTree. The class NTree is recursive, having pointer to NTree inside it.
This is what I'm struggling with.
I understand the logic behind a destructor, if we have e.g.
class MyClass
{
private:
TypeA * myA;
TypeB * myB;
TypeC * myC;
...
}
We could use a destructor to prevent these pointers from dangling, or getting lost.
~MyClass()
{
delete myA;
delete myB;
delete myC;
}
However, when it comes to a recursive class, I have no clue how to wrap my mind around this, how to understand deletion.
A simple thing to think of:
template<class T, int N>
NTree<T, N>::~NTree()
{
delete[] fNodes;
}
However, it won't work, as some nodes are NIL (stack allocated), so deleting them will result in a crash.
Another idea is:
template<class T, int N>
NTree<T, N>::~NTree()
{
for (int i = 0; i < N; i++)
{
delete fNodes[i];
}
}
However, this will result in a stack overflow, because of the stack being bombarded with frames for each recursive call of ~NTree()
And the following:
template<class T, int N>
NTree<T, N>::~NTree()
{
for (int i = 0; i < N; i++)
{
if (fNodes[i] != &NIL)
delete fNodes[i];
}
}
Results in a read exception, because the recursive calls will deallocate fNodes[i] for a particular stack frame, thus trying to access that memory is invalid.
So my question is, how can I delete a member variable, where that member is recursively defined as the same class?
How can I make my destructor work?
Edit: Attempt to provide more information without making it too convoluted
I'm defining a destructor so it's probably wise to show you my copy constructor and assignment operator:
template<class T, int N>
NTree<T, N> & NTree<T, N>::operator=(const NTree & aOtherNTree)
{
//This is an already initialized object.
if (this != &aOtherNTree)
{
fKey = aOtherNTree.fKey;
for (int i = 0; i < N; i++)
{
if (fNodes[i] == &NIL)
continue; //continue if nil
delete fNodes[i]; //important -- so no dangling pointer
fNodes[i] = new NTree<T, N>; //allocate memory
fNodes[i] = aOtherNTree.fNodes[i]; //assign
}
}
return *this;
}
..
template<class T, int N>
NTree<T, N>::NTree(const NTree & aOtherNTree)
{
//This is a new object, nothing is initalized yet.
fKey = aOtherNTree.fKey;
for (int i = 0; i < N; i++)
{
if (fNodes[i] == &NIL)
continue;
fNodes[i] = new NTree<T, N>;
fNodes[i] = aOtherNTree.fNodes[i];
}
}
I hope this shows all instances of when I allocate memory that needs explicit deletion in the destructor.
NIL is a sentinel, we always assign a leaf to NIL.
This part is provided by the professor, it is where we set up the initial objects:
NS3Tree root(A);
root.attachNTree(0, *(new NS3Tree(A1)));
root.attachNTree(1, *(new NS3Tree(A2)));
root.attachNTree(2, *(new NS3Tree(A3)));
root[0].attachNTree(0, *(new NS3Tree(AA1)));
root[1].attachNTree(0, *(new NS3Tree(AB1)));
root[1].attachNTree(1, *(new NS3Tree(AB2)));
A1, A2, etc, are strings
Your copy constructor and assignment operator are both totally wrong.
if (fNodes[i] == &NIL)
continue; //continue if nil
delete fNodes[i]; //important -- so no dangling pointer
This is wrong logic. If your old child value was NIL, it will stay NIL forever, because it will be never assigned. This should be:
if (fNodes[i] != &NIL)
delete fnodes[i];
Of course in the copy ctor the above fragment should not appear, because fNodes[i] doesn't have any determined value. It should only appear in the assignment.
Now
fNodes[i] = new NTree<T, N>; //allocate memory
fNodes[i] = aOtherNTree.fNodes[i]; //assign
You allocate some node and then immediately overwrite a pointer to it with another pointer, managed by another node. The first assignment thus has no effect, except for a memory leak. The second one will result in an error later on. Here's a correct invocation
if (aOtherNTree.fNodes[i] == &NIL)
fNodes[i] = &NIL;
else
fNodes[i] = new NTree<T, N> (*aOtherNTree.fNodes[i]); // make a new copy
An alternative else clause is
else {
fNodes[i] = new NTree<T, N>;
*fNodes[i] = *aOtherNTree.fNodes[i]); // assign the object, not the pointer
}
I recommend writing a debugging function that would print a tree, including the address of each node. While debugging, print every tree you make to ensure no pointer sharing occurs.

Deep copy int array c++

I want to deep copy an array of int. I get an Assertion Error: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse) when it goes through the destructor. Which I've been told is because It's trying to delete something that is not there. Please let me know if I am on the right track and just need to change something small, or if I am completely lost and don't know it. I can add more code if needed.
Thanks for the answers.
.h
private:
int* _myArray;
int _size;
int _capacity;
.cpp
MyVector::MyVector()
{
_myArray = new int[2];
_size = 0;
_capacity = 2;
}
MyVector::MyVector(int aSize)
{
_myArray = new int[aSize];
_size = 0;
_capacity = aSize;
}
MyVector::~MyVector()
{
if(_myArray != NULL)
{
delete[] _myArray;
_myArray = NULL;
}
}
MyVector::MyVector(const MyVector& mVector)
{
_capacity = mVector._capacity;
_size = mVector._size;
// if(mVector._myArray)
// {
// _myArray = new int[_capacity];
// copy(mVector._myArray, mVector._myArray+_capacity, _myArray);
// }
}
MyVector& MyVector::operator=(MyVector& setterVect)
{
delete [] _myArray;
if(setterVect._myArray)
{
_myArray = new int[_capacity];
copy(setterVect._myArray, setterVect._myArray+_capacity, _myArray);
}
return *this;
}
You need to make sure you are following the "Rule of Three".
Apart from copy constructor & destructor You should also provide a copy assignment operator which should do a deep copy of dynamically allocated pointer member.
On a side note, the best solution is to simply drop the dynamically allocated member and use a std::vector it saves you all the hassles of manual memory management.

can't delete array that is class field

I have class cAuthorisation that manages array of strAuthorisation
function resize prepares aray for next record.
During resize , on line delete [] data; I have crash.
struct strAuthorisation
{
double Amount;
}Authorisation;
class cAuthorisation {
public:
int size;
strAuthorisation *data;
cAuthorisation ()
{
size=0;
}
~cAuthorisation()
{
};
void Add(strAuthorisation )
{
resize();
data[size]=*value;
}
void resize()
{
strAuthorisation *a = new strAuthorisation[5];
size_t newSize = size + 1 ;
strAuthorisation *newArr = new strAuthorisation[newSize];
memcpy( newArr, data, size * sizeof(strAuthorisation) );
size = newSize;
delete [] data;
data = newArr;
}
} Authorisations;
Why it is not possible delete class array?
It crashes because data is an unitialised pointer. delete[] on a null pointer is safe (no-op) so initialise data in the constructor:
cAuthorisation() : size(0), data(0) {}
Note that the class as it stands is violating the rule of three.
Unsure if this is a learning exercise, if it is not use std::vector<strAuthorisation>. The std::vector will dynamically grow as required and automatically destructed when it goes out of scope.
You have not initialized the data pointer. So you are making something like this:
Foo *data;
delete [] data;
"data" is a pointer who's value was never initialized.