LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   Destructor called on objects in deque without it being called explicitly (https://www.linuxquestions.org/questions/programming-9/destructor-called-on-objects-in-deque-without-it-being-called-explicitly-891444/)

Snark1994 07-13-2011 04:13 AM

Destructor called on objects in deque without it being called explicitly
 
I feel there's a bit of a misunderstanding going on between C++ and me...

My problem is that I have a deque of pointers to a class, and create objects then add them to the deque in a for loop. However, the destructor is called on the object as soon as the loop quits.

Code:

#include <deque>
#include "stdio.h"

class Test {
    private:
        static int number;
        int id;
    public:
        Test(void);
        Test(const Test&);
        ~Test(void);
};
 
int Test::number = 0;

Test::Test(void){
    id = ++number;
    printf("Creating number %d\n",id);
}

Test::Test(const Test& old){
    id = old.id;
    printf("Copying number %d\n",id);
}

Test::~Test(void){
    printf("Deleting number %d\n",id);
}

int main(void){
    std::deque<Test*> myDeque;
    int i;
    for(i=0;i<5;i++){
        printf("\ni is now %d\n",i);
        Test temp;
        myDeque.push_front(&temp);
    }
    printf("Out of loop\n\n");
    return 0;
}

This prints:

Code:

i is now 0
Creating number 1
Deleting number 1

i is now 1
Creating number 2
Deleting number 2

i is now 2
Creating number 3
Deleting number 3

i is now 3
Creating number 4
Deleting number 4

i is now 4
Creating number 5
Deleting number 5
Out of loop

Now, if I change the deque from deque<Test*> to deque<Test> then it works fine - I get:

Code:

i is now 1
Creating number 1
Copying number 1
Deleting number 1
...
Out of loop
...
Deleting number 5
Deleting number 4
...
Deleting number 1

However, I can't do this with my actual code, because I am creating a deque of pointers to an abstract class, so it won't let me instantiate the class. (This is all so that I can take advantage of polymorphism, and call functions on a set of similar objects without worrying what type of object I'm dealing with).

So, I suppose my question is: what is the correct way to create that deque of pointers to the abstract class? I don't seem to be barking up the right tree currently.

Thanks in advance :)

dwhitney67 07-13-2011 05:18 AM

You've declared a local object in your for-loop, which gets destroyed with each iteration of the loop.
Code:

Test temp;
If you want the objects to persist beyond the scope of the loop, then do something like:
Code:

Test* temp = new Test;
myDeque.push_front(temp);

P.S. Don't forget to delete the allocated object(s) at a later time.

Snark1994 07-13-2011 06:58 AM

Brilliant, thank you very much.

With regards to your postscript, do you just mean that when popping the objects I should do:

Code:

delete mydeque.back();
mydeque.pop_back();

Or do I need to do something more to ensure they are deleted correctly?

dwhitney67 07-13-2011 07:11 AM

Quote:

Originally Posted by Snark1994 (Post 4413673)
Brilliant, thank you very much.

With regards to your postscript, do you just mean that when popping the objects I should do:

Code:

delete mydeque.back();
mydeque.pop_back();

Or do I need to do something more to ensure they are deleted correctly?

What you have above is fine; however don't you want to have a handle to the Test object to do something with it?
Code:

Test* test = mydeque.back();
mydeque.pop_back();

// do something with test
...

delete test;


Snark1994 07-13-2011 08:05 AM

Yes, sorry, I just meant for how I go about deleting the object. Thankyou :)

However, it turns out there's an additional complication due to the fact that I'm using an abstract class.

Code:

#include <deque>
#include "stdio.h"

class MetaTest {
        public:
                virtual void something(void)=0;
};

class Test: public MetaTest {
        private:
                static int number;
                int id;
        public:
                Test(void);
                Test(const Test&);
                ~Test(void);
                void something(void){};
};

int Test::number = 0;


Test::Test(void){
        id = ++number;
        printf("Creating number %d\n",id);
}

Test::Test(const Test& old){
        id = old.id;
        printf("Copying number %d\n",id);
}

Test::~Test(void){
        printf("Deleting number %d\n",id);
}

int main(void){
        std::deque<MetaTest*> myDeque;
        int i;
        for(i=0;i<5;i++){
                printf("\ni is now %d\n",i);
                Test* temp = new Test;
                myDeque.push_front(temp);
        }
        printf("Out of loop\n\n");

        printf("Starting to delete:\n");
        while(myDeque.size() > 0){
                delete myDeque.back();
                myDeque.pop_back();
        }
        return 0;
}

My guess is that because I'm using a pointer to the MetaTest class, it doesn't know it has to call the Test destructor. Is there a way around this? Or do I have to write another virtual method in the MetaTest called "deleteMe()" which is then overridden in each of the derived classes and called before I delete the object?

EDIT: Never mind. For others asking the same question, read this article on virtual destructors. I fixed it by adding a "virtual ~MetaTest(void)" declaration and defining it as "MetaTest::~MetaTest(void) { }"

Thanks again,


All times are GMT -5. The time now is 05:50 AM.