vector <T *> destructor [closed] - c++

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I have a class defined like:
Class A
{
public:
int num;
A *parent;
vector<A *> children;
...
// constructor without parameters
A(void)
{
this->num = 3;
this->parent = 0;
for (int i=0;i<num;++i)
children.push_back(new A(this,num-1));
}
// constructor with parameters
A(A *a,int n)
{
this->num = n;
this->children->parent = a;
for (int i=0;i<num;++i)
this->children.push_back(new A(this,this->num-1));
}
};
now, the constructor works fine. there are some problem with destructor.
currently, the destructor is defined as:
A::~A(void)
{
if (this->parent!=0) this->parent = 0;
for (int i=0;i<(int)children.size();++i)
this->children[i]->~A();
vector <A *> ().swap(this->children);
}
but every time when I debug it, it will break at:
void deallocate(pointer _Ptr, size_type)
{ // deallocate object at _Ptr, ignore size
::operator delete(_Ptr);
}
it looks like I cannot delete the pointer in the vector of this->children, is there any way that I can de-construct the class successfully?

Your destructor should be:
A::~A(void)
{
for (size_t i=0; i < children.size(); ++i)
delete children[i];
}
You should probably also look into copy constructors. Otherwise, code like this will fail:
{
A foo;
B bar = foo;
}
Becuase you will delete the same pointers twice.
One of these two posts may help you with understanding that: 1 and 2

in the destructor of A, you shouldn't call the destructors of child items explicitly, instead, just delete the elements of the vector. this should be sufficient for your purpose:
A::~A(void)
{
for (size_t i=0; i<children.size(); ++i)delete children[i];
}

Your constructor with parameters has a typo bug in it - this->children->parent will not compiler as children is not a pointer nor does vector have a parent member. I suspect you meant to use this->parent instead.
Your destructor is directly calling the destructor of each child object, which will destroy the child but NOT free its memory. You allocate the child objects with the new operator, so you need to use the delete operator to call the destructor and free the memory correctly.
On a side note, your num member is redundant. You can use children.size() wherever num is needed.
Try this instead:
class A
{
private:
static const int default_num = 3;
public:
A *parent;
vector<A *> children;
...
// default constructor
A()
{
parent = 0;
for (int i = 0; i < default_num; ++i)
children.push_back(new A(this, default_num-1));
}
// constructor with parameters
A(A *a, int n)
{
parent = a;
for (int i = 0; i < n; ++i)
children.push_back(new A(this, n-1));
}
~A()
{
parent = 0;
for (vector<A *>::size_type i = 0; i < children.size(); ++i)
delete children[i];
/*
alternatively:
for (vector<A *>::iterator i = children.begin(); i != children.end(); ++i)
delete *i;
*/
children.clear(); // optional, will be handled when vector is implicitally destructed
}
};

Related

Resize array using new

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.

Using shared_ptr for linked_list gives stackoverflow within destructor

I'm trying to implement a linked list using shared_ptr rather than raw pointers. The code :
#include <memory>
class NodeTest
{
private:
int v;
std::shared_ptr<NodeTest> next;
public:
NodeTest() { v = 0; };
NodeTest(unsigned int i) { v = i; }
~NodeTest() {};
void setNext(std::shared_ptr<NodeTest> & toSet) { next = toSet; }
};
std::shared_ptr<NodeTest> init()
{
std::shared_ptr<NodeTest> elt = std::shared_ptr<NodeTest>(new NodeTest());
std::shared_ptr<NodeTest> first = elt;
for (unsigned int i = 1; i < 5000; i++)
{
std::shared_ptr<NodeTest> next(new NodeTest(i));
elt->setNext(next);
elt = next;
}
return first;
}
void test_destroy()
{
std::shared_ptr<NodeTest> aList = init();
}
int main(int argc, char * argv[])
{
test_destroy();
}
This is generating a stackoverflow when leaving test_destroy() scope because of the call to aList destructor (RAII). To destroy aList, it calls the destructor of next and so on, which obviously ends up with a stackoverflow for a sufficiently large list.
I can't find any efficient way to fix this. The ideal case would be to delete the current NodeTest before moving to next deletion, right? How would you do such a thing?
Thanks in advance
Solution : You need to break the links between all nodes AND save a pointer to each node so that the destructor is not immediatly called upon breaking links. Example below using a vector.
~NodeTest()
{
std::vector<std::shared_ptr<NodeTest>> buffer;
std::shared_ptr<NodeTest> cursor = next;
while (cursor.use_count()!=0)
{
std::shared_ptr<NodeTest> temp = cursor->getNext();
cursor->setNext(std::shared_ptr<NodeTest>());
buffer.push_back(cursor);
cursor = temp;
}
next = std::shared_ptr<NodeTest>();
};
In this case you should manage nodes deleting manually because destructor calls destructor calls destructor .....
Take a look on the talk CppCon 2016: Herb Sutter “Leak-Freedom in C++... By Default.”
The destructor of NodeTest invokes the destructor of NodeTest::next which recursively calls another NodeTest destructor and so on until the stack is exhausted. Smart-pointers should not be used for linking nodes for this reason.

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 :)

Could class default initialize its "pointer member variable"?

struct Node{
Node* ch[26];
string str;
Node(){
for(int i = 0; i < 26; i++) {
ch[i] = NULL;
}
str = "";
}
};
class Solution {
public:
vector<string> results;
Node* root;
void insert(Node* p, string s) {
int len = s.size();
for(int i = 0; i < len; i ++) {
if(p->ch[s[i] - 'a'] == NULL) {
p->ch[s[i] - 'a'] = new Node();
}
p = p->ch[s[i] - 'a'];
}
p->str = s;
}
vector<string> wordSearchII(vector<vector<char> > &board, vector<string> &words) {}
}
This is the Trie I defined for my problem. The "root" and "vector result" are both member variables of Solution. The question I want to ask is that why I must "new Node()" before I use root. I do not need to "new vector" before I use results. I understand that the Solution will call default constructor and then "results" will call its default constructor. Why couldn't root use the default constructor of Node?
I happen to realize that my confuse may relate to "pointer". But I still don't understand the details. Can anyone explain about it? I really appreciate it.
root is just a pointer, but you are not assigning anything for it to point at. You need to allocate a new Node object and then assign the address of that object to root, eg:
class Solution {
public:
vector<string> results;
Node* root;
Solution() {
root = new Node;
}
~Solution() {
delete root;
}
...
};
Otherwise, don't make root be a pointer at all:
class Solution {
public:
vector<string> results;
Node root;
...
};
On a side note, your Node class needs a destructor to destroy any child nodes that are added to it:
struct Node{
Node* ch[26];
string str;
Node(){
for(int i = 0; i < 26; i++) {
ch[i] = NULL;
}
}
~Node(){
for(int i = 0; i < 26; i++) {
delete ch[i];
}
}
};
In
Node* root;
The * means that root is a pointer to a Node object, it is not an actual Node object itself. The only storage a pointer has is enough to hold the memory address of whatever the pointer is pointing at. A pointer has to point at something. Right now, you have no idea what root points at, and this is... bad. You have no idea what you'll get if you try to read from it, and you have no idea what you'll smash if you try to write to it. You need to assign something for root to point at, and if that's a new Node(), so be it, but it could also be a pre-existing Node, or a Node in automatic storage (AKA somewhere on the stack).
On the other hand, in
vector<string> results;
results is not a pointer to a vector object. It is the actual vector object. It is the storage. There is no need to allocate memory for it, simply declaring it on the stack allocates everything for it and calls its default constructor.

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.