Question

I have an object called a Chunk that holds a pointer to a b2Body. It does other important things, but i removed those for simplicity. Heads up, smart pointers won't work(I think), you'll see why.

class DChunk
{
public:
    DChunk();

    DChunk(const DChunk& old);
    virtual ~DChunk();

    virtual b2Body* getBody() const;

private:
    b2Body* m_pBody;//pointer;
};

The question is, how to define when to delete the m_pBody object.

If I want to copy this object, like say there is a vector of these things and I push_back another, it will call the Copy Constructor, copy the memory address of m_pBody(thats what i want), and then delete the old one. If the Destructor on this object deletes m_pBody, that's obviously bad, because the new copy wont have a valid memory address, but if it doesn't delete it, then m_pBody will never be deleted, and it needs to be deleted when there are no more Chunks pointing at it.

The only correct way to delete the m_pBody object is to call m_pBody->GetWorld()->DestroyBody( m_pBody ); and thats not under my control, so smart pointers dont really work. I was hoping there would be different types of destructors that get called appropriately, like when a copy has been made in a vector. Also, there should never be more than one Chunk associated with one b2Body, if that is helpful.

Was it helpful?

Solution

I will assume you have something like

    vector<DChunck> myvec;

and you are worried about doing

    obj=DChunk()
    myvec.push_back(obj)

First of all (this is very beginner friendly approach, avoiding smart pointers or any C++11) there's something not quite correct about creating a container DChunk objects. That's because when you declare

    vector<DChunk>

you are telling your vector that it will receive objects the size of DChunk. However, since that class contains a pointer to an array, m_pBody (array's size will not be constant!), this approach will not be too "healthy" for C++. Given this, you can do something else, sticking to your class design: create a container of pointers! You can create

    vector<DChunk*> myvec;

and if you want to add an object to that vector, you just do

    DChunk *obj = new DChunk();
    myvec.push_back(event);

since now the container is handling pointers, which can be juggled around without interfering with the objects content, avoiding the worries concerning a destructor. Calling an object's method will now be, for example,

    (*myvec[3]).getBody()

or (cleaner version)

    myvec[3]->getBody()

Hope I addressed your question

OTHER TIPS

You can also provide move constructor so that instead of copying, it would move stuff... Here's an example that I made some hours ago, because I had the same problem (I didn't know in what order would these constructors and when be called, also "&&" is move constructor):

A move constructor is similar to copy constructor. The difference is that in move constructor instead of copying values and stuff, you assign given object's pointers (not copy) and values to a new one (this->temp = OldClass.temp) and then make OldClass.temp = NULL; so that when the unavoidable destructor is called, it finds a NULL pointer and does not delete it.

#include <iostream>
#include <Windows.h>

class MyClass
{
public:
    MyClass()
    {
        temp = new RECT();
        ZeroMemory(temp, sizeof(RECT));
    }
    MyClass(int x, int y)
    {
        temp = new RECT();
        ZeroMemory(temp, sizeof(RECT));
        temp->left = x;
        temp->top = y;
    }
    MyClass(MyClass &&OldClass)
    {
        if (this->temp != NULL)
        {
            delete this->temp;
            this->temp = NULL;
        }
        temp = OldClass.temp;
        OldClass.temp = NULL;
    }
    MyClass& operator=(MyClass &&OldClass)
    {
        if (this->temp != NULL)
        {
            delete this->temp;
            this->temp = NULL;
        }
        temp = OldClass.temp;
        OldClass.temp = NULL;
        return *this;
    }
    MyClass(const MyClass &OldClass)
    {
        *temp = *OldClass.temp;
    }
    MyClass& operator=(const MyClass &OldClass)
    {
        *temp = *OldClass.temp;
        return *this;
    }
    ~MyClass()
    {
        if (this->temp != NULL)
        {
            delete this->temp;
            this->temp = NULL;
        }
    }
    void Print()
    {
        std::cout << temp << " " << temp->left << " " << temp->top << " " << temp->right << " " << temp->bottom << '\n';
    }
private:
    RECT *temp;
};

int main()
{
    MyClass bla, cha(54, 48);
    bla.Print();
    cha.Print();
    bla = MyClass(2, 2);
    bla.Print();
    bla = cha;
    bla.Print();
    cha = MyClass(54, 2);
    cha.Print();
    std::cin.get();
    return 0;
}

In common, a proper memory management is non trivial task and no universal decision are existing. Some simple and common well-known methods are presented as "smart pointer" types in newest libraries (and you can also define them yourself (by copy known "standard definition")). But it also is not an completely universal :-) And your question seems to be a question for a such universal solution. Some other programming languages (java ... , not C++) advertise you to get rid of that problem (by the built-in methods of language implementations). You write: "Also, there should never be more than one Chunk associated with one b2Body, if that is helpful." . And then the problem seems to disappear (because the Chunk cannot be copied at all). (?)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top