Reputation: 81
I have a queue class wherein I'm trying to dynamically allocate 3 "sample" objects and place them into a queue, and then dequeue and delete them. But the destructor for the sample objects:
~Sample() { cout << "Destructing Sample object " << id << "\n"; }
Is for some reason being called when I try to put the objects on the queue.
int main()
{
Sample *samp1;
Sample *samp2;
Sample *samp3;
Queue<Sample> sQa(3);
samp1 = new Sample(1);
samp2 = new Sample(2);
samp3 = new Sample(3);
cout << "Adding 3 Sample objects to queue...\n";
sQa.put(*samp1);
sQa.put(*samp2);
sQa.put(*samp3);
cout << "Dequeing and destroying the objects...\n";
for(int i = 0; i < 3; ++i)
{
delete &sQa.get();
}
return 0;
}
Here is the output:
Adding 3 sample objects to queue...
Destructing Sample object 1
Destructing Sample object 2
Destructing Sample object 3
Dequeing and destroying the objects...
Destructing Sample object 1
And then the program crashes. Anyone know why this might be? Also, here is the put function in case it is necessary. (the queue class is a template)
void put(Qtype data)
{
if(putloc == size)
{
cout << " -- Queue is full.\n";
return;
}
putloc++;
q[putloc] = data;
}
Upvotes: 2
Views: 754
Reputation: 254411
You code allocates objects; copies them into the queue; retrieves copies from the queue; and tries to delete those copies. The original objects are leaked (since you don't delete samp1
etc.), and the final objects can't be deleted since they weren't created with new
.
The destructors you're seeing are from temporary objects created while you copy the allocated objects into the queue; the crash is the undefined behaviour you get from deleting the wrong object.
Since the queue contains objects, not pointers, there is no need to mess around with dynamic allocation at all:
cout << "Adding 3 Sample objects to queue...\n";
sQa.put(Sample(1));
sQa.put(Sample(2));
sQa.put(Sample(3));
cout << "Dequeing and destroying the objects...\n";
for(int i = 0; i < 3; ++i)
{
sQa.get();
}
If you want to experiment with dynamic allocation, then you should modify the queue to store pointers; but remember that it's very difficult to manage dynamic objects without the help of RAII so don't try this in any code that needs to be reliable.
Upvotes: 1
Reputation: 56479
The root of your problem
delete &sQa.get();
You're deleting something which is irrelevant to the allocated objects by new
.
The correct way is something like below:
Queue<Sample*> sQa(3);
samp1 = new Sample(1);
samp2 = new Sample(2);
samp3 = new Sample(3);
sQa.put(samp1);
sQa.put(samp2);
sQa.put(samp3);
cout << "Dequeing and destroying the objects...\n";
for(int i = 0; i < 3; ++i)
{
delete sQa.get();
}
Note: it's better to use smart pointers such as unique_ptr
or shared_ptr
instead bare pointers.
Upvotes: 3
Reputation: 1235
Unless Qtype is a typedef, your put() function specifies its parameter should be passed by copy. Whenever you call it, it will call Sample's copy constructor to create a temporary object.
Upvotes: 1
Reputation: 206498
Your code causes Undefined behavior. It calls delete
on a object which was not dynamically allocated using new
.
With:
sQa.put(*samp1);
You store a copy of the dynamically allocated member in sQa
. You lost the pointer to dynamically allocated objects once you copied the object by value.
The solution is to use smart pointer as the container element and let RAII do all the hard work of memory management for you.
Upvotes: 10