Reputation: 347
Funky title, but honestly I couldn't think of anyone better, sorry :(
While experimenting with pointers I came across this and I need help understanding it. Basically, I create a vector of a pointer to an object. When deleting the pointer that's in the vector, I expect the original ovject to be deleted as well. They are one and the same no?
Here's what I think I do in the code that follows I create a dynamically allocated array, I then put the pointer to half of the elements of the array in a vector of pointers. Each step of the way every object of the class testDestructor knows which 'order' it was created in, they all get assigned an incrementing number via a static integer.
I then pop_back and delete all the pointers in the vector. I only use pop_back because I wanted to see if they get deleted by the vector class, apperantly they don't, but idk if I'm missing something there. The important bit is I delete it.
Now, what I expect to happen is that this deletes the corresponding elements of the array as well. This is what SHOULD happen, because the vector and the array element point to the same place in the memory. ie, the destructor should get called.
So when I then delete the array, I expect that either only 5 of the elements get deleted, or a run-time error occurs (I've had this happen before when I try deleting pointers that already are deleted, but that might have been a different scenario idk). Namely, I expect that only the destructor should only be called five times.
HOWEVER, that's not what happens. The constructor gets called 10 times but the destructor gets called 15 times. What am I missing? Am I missing a constructor (I only know about default constructors and copy constructors, are there more), or is it something else? Because, in my mind, when the destructor is gone the object is gone.
Sorry if it's too much code:
testDestructor.h:
#ifndef TESTDESTRUCTOR_H
#define TESTDESTRUCTOR_H
class testDestructor
{
public:
testDestructor();
testDestructor(const testDestructor &);
~testDestructor();
static int maxTest;
int test;
};
#endif
testDestructor.cpp:
#include "testDestructor.h"
#include <iostream>
using namespace std;
int testDestructor::maxTest = 0;
testDestructor::testDestructor()
{
test = maxTest++;
cout << "testDestructor nr " << test << " created successfully\n";
}
testDestructor::testDestructor(const testDestructor &destructorToCopy)
{
test = maxTest++;
cout<< "testDestructor nr " << test << " created successfully (using the copy constructor\n";
}
testDestructor::~testDestructor()
{
//maxTest--;
cout << "testDestructor " << test << " destroyed successfully\n";
}
main.cpp:
#include <iostream>
#include "testDestructor.h"
#include <vector>
using namespace std;
int main()
{
cout << " creating pointer array:\n\n";
testDestructor *testPtr = new testDestructor[10];
cout << " intitiating vector\n\n";
vector<testDestructor*> testVct;
for (int i = 0; i < 5; i++)
{
cout << " pushing back vector " << i << ":\n";
testVct.push_back(testPtr + i);
cout << "testDestructor " << testVct[i]->test << " pushed back\n";
}
cout << "\n";
for (int i = 4; i >= 0; i--)
{
cout << " popping back vector " << i << ":\n";
cout << "testDestructor " << testVct[i]->test << " popped back\n";
delete testVct[i];
testVct.pop_back();
}
cout << "\n";
cout << " deleting pointer array\n\n";
delete [] testPtr;
}
Upvotes: 0
Views: 1545
Reputation: 164
First
In my test, this program will core dump at 'delete testVct[i];'
My g++ version is 4.1.6
Maybe you can init testPtr:
testDestructor *testPtr[10];
for(int i=0;i<10;i++)
testPtr[i] = new testDestructor;
Second
you delete a pointer twice 1) delete testVct[i]; 2) delete [] testPtr;
Upvotes: 0
Reputation: 83557
First of all, let's look at your variable declarations:
testDestructor *testPtr = new testDestructor[10];
vector<testDestructor*> testVct;
This says that testPtr is a pointer to an object of type testDestructor and testVct is a vector of pointers to objects of type testDestructor.
In addition, you allocate an array of testDestructor objects with the new operator and assign the address of the first element in testPtr. Now testPtr can be used as an array to testDestructor objects.
Note that you have not allocated memory for any individual testDestructor objects. This means that you delete any pointers to the objects in the array will result in undefined behavior. On the other hand, using delete[] on testPtr to deallocate the array is permissible.
The general rule here is that every delete or delete[] must have a matching new or new[] and vice versa.
Upvotes: 0
Reputation: 68053
When deleting the pointer that's in the vector, I expect the original ovject to be deleted as well. They are one and the same no?
No, they're not the same, and your terminology "deleting the pointer" implies you need to go and re-read some basic stuff about pointers in C++.
new
creates things, and returns a pointer to what it creates. delete
destroys things and is passed a pointer to the thing to destroy. The pointer is unchanged - it just doesn't point anywhere useful following a delete.
What you're trying to do is delete
individual objects in an array of objects created with new[]
. That simply cannot be done. You can only delete the whole lot with delete[]. If you want to have individually deleteable objects, use a std::vector<TestDestructor>
.
Upvotes: 2
Reputation: 9278
operator delete[]
will call the destructors of the items in the array before it deletes the array itself. If you wish to delete some of the items in the array manually you need to set its array index value to NULL
afterwards. Calling the destructor twice on the same object is undefined behaviour and will hopefully end badly for you.
Upvotes: 1
Reputation: 25464
The issue here is that the first five instances of testDestructor
are deleted twice: Once by delete testVct[i]
and another time by delete [] testPtr;
.
The first delete
is wrong.
The objects are owned by testVct
and thus their destruction may be carried out only through delete[]
ion of testVct
. You can delete
individual objects only if they are allocated by new
.
Upvotes: 1