Hi,
I've made a class whose member is a reference to a dynamically created object. How should I code a destructor?

If the reference (e.g. int*& thingy;) was actually allocated somewhere else then your class destructor should not do anything with it. Let whatever created it destroy it.

Edited 6 Years Ago by Ancient Dragon: n/a

Without knowing exactly how your class works, it's hard to say.

However, a good rule of thumb:
If you use the "new" keyword in the class' constructor, you will need to use the "delete" keyword in the matching destructor.

[edit]
Looks like AD beat me to it.

Edited 6 Years Ago by Fbody: n/a

Without knowing exactly how your class works, it's hard to say.

However, a good rule of thumb:
If you use the "new" keyword in the class' constructor, you will need to use the "delete" keyword in the matching destructor.

[edit]
Looks like AD beat me to it.

This is what I was actually asking about. They are created with "new".
My classes are of this kind:
class WindowsList;
class WindowsListElement;
class Window;

WindowsList is a container that keeps WindowsListElement objects (nevermind how) WindowsListElement has a reference to a Window object.

Window objects are created in different places. Most are created by a global function. I create them with "new". Next the constructor of WindowsListElement is called with the just created Window object as a parameter. Then the WindowsListElement is put into the proper container.

Destruction goes this way. I destroy the container. I calls the destructors of its elements. Now they have to destroy the Windows objects that they have as reference members.

Is this alright? How should it be? I'm new to this stuff, and have problems with basics. Can I delete the member or do I have to delete the address of it? AFAIK "delete" goes with pointers, not with the very objects?

That would depend on the inteded usage of your class. You do not say, or show with an example code snippet, how you are using the class. Is the class intended to manage a resource? Is the dynamically allocated object created by this class or does it live elsewhere? You say you have a reference to it, do you mean a reference or do you have a pointer?

If you are using a class to manage a resource, following the RAII idiom, then your class destructor should release the resource, be it allocated memory or whatever. Ensure you use the correct combinations of new and delete, new[] delete[] to avoid problems.

Something else to give consideration to in this case is how to handle copying behaviour of a resource managing class. Say your class is managing a chunk of memory for example you need to decide whether it makes sense to allow copying of this, if it is then you msut ensure you correctly copy all of the memory. Otherwise you could prevent copying or transfer ownership of the resource instead, or you could implement a reference counted resource and have a single copy of the managed resource and many objects referring to it. in this case your destructor would need to take this into account and only free the resource once the last object referring to it had been destroyed.

Something else to consider is the use of smart pointers to manage the dynamically allocated object.

Whatever yoiu are intending, to give a more specific answer you need to provide a bit more detail on what you intend.

That would depend on the inteded usage of your class. You do not say, or show with an example code snippet, how you are using the class. Is the class intended to manage a resource? Is the dynamically allocated object created by this class or does it live elsewhere? You say you have a reference to it, do you mean a reference or do you have a pointer?
It is a reference.

Something else to give consideration to in this case is how to handle copying behaviour of a resource managing class. Say your class is managing a chunk of memory for example you need to decide whether it makes sense to allow copying of this, if it is then you msut ensure you correctly copy all of the memory. Otherwise you could prevent copying or transfer ownership of the resource instead, or you could implement a reference counted resource and have a single copy of the managed resource and many objects referring to it. in this case your destructor would need to take this into account and only free the resource once the last object referring to it had been destroyed.
It is not a commercial program or anything like that. I does not have to perfect. I simply know I don't ever copy anything in the code, so I didn't even bother banning copying. No-one will ever use this code :-)

Something else to consider is the use of smart pointers to manage the dynamically allocated object.

Whatever yoiu are intending, to give a more specific answer you need to provide a bit more detail on what you intend.
Please look at what I've posted just a second before you.

It would be hard to give a snippet of the code. I can try but the code is very long.

Edited 6 Years Ago by mmasny: n/a

Ok. So you are using your class to hold details of a resource which is created externally to your class. You need to think about whether those objects are meaningful or useful to you after the destruction of your WindowsList, if so then there is no need to delete them in the destructors as such but you would still need to ensure they were deleted elsewhere. If they are meaningless without the containers, i.e. the containers are effectively managing the resource, then you should delete them.

Note new returns a pointer. You say you are storing a reference to an object, how are you doing this?

Obj *obj = new Obj;

Obj& obj_ref = *obj;

Something like that? More detail is still required. Some code would be nice.

Ok. So you are using your class to hold details of a resource which is created externally to your class. You need to think about whether those objects are meaningful or useful to you after the destruction of your WindowsList, if so then there is no need to delete them in the destructors as such but you would still need to ensure they were deleted elsewhere. If they are meaningless without the containers, i.e. the containers are effectively managing the resource, then you should delete them.
It's more complicated than that. But to simplify, when I destroy the container I am sure the elements are to be destroyed as well.
Note new returns a pointer. You say you are storing a reference to an object, how are you doing this?

Obj *obj = new Obj;

Obj& obj_ref = *obj;

Something like that?
Exactly. Only that the reference is a member of the class so it is initialized in the initialisation list of the constructor.
More detail is still required. Some code would be nice.
OK I'll try to deliver some of it. The program is now 750 lines long and is really complicated (for me) so it's going to be hard.

M
PS: another problem is that the names of everything in the code will be meaningless to you. They're in Polish.

Edited 6 Years Ago by mmasny: n/a

M
PS: another problem is that the names of everything in the code will be meaningless to you. They're in Polish.

class Okno;     //declaration of the class Window. full definition below.

class ListaOkienEl{      //definition of the class WindowsListElement
  
    ListaOkienEl* next;  //pointer to the next element on the list
    Okno& el;       //contained window
    

public:
    ListaOkienEl(Okno&);
    ListaOkienEl(const ListaOkienEl&); 
    ~ListaOkienEl();
    ListaOkienEl* WezNastepny(){return next;} //returns a pointer to the next item on the list
    Okno& WezElement(){return el;}              //returns a reference to the Window object
};
ListaOkienEl::~ListaOkienEl(){
    //What should be here??????
}

class ListaOkien{                              //defition of the class WindowsList
    ListaOkienEl* pocz;   //a pointer to the first item on the list
public:
    ListaOkien();
    ~ListaOkien();
    void DodajPocz(ListaOkienEl&);
    void UsunPocz(); //destroys the first item on the list 
    ListaOkienEl* WezPocz();
    ListaOkienEl* WyjmijOkno(string nazwa);
    void Przenies();
};

//methods of WindowsList
ListaOkien::ListaOkien(){   
    pocz=NULL;
}

ListaOkien::~ListaOkien(){
    while(pocz)
        UsunPocz();
}

void ListaOkien::DodajPocz(ListaOkienEl& NowyElement){ //put the argument at the begining of the list
    //delete NowyElement.WezNastepny(); //kasuje to na co do tej pory wskazywal? czy to dobrze?
    NowyElement.UstawNastepny(pocz);
    pocz=&NowyElement;
}

void ListaOkien::UsunPocz(){  //destroys the first object on the list and sets the begining of the list on the next element
    ListaOkienEl* pom=pocz->WezNastepny();
    delete pocz;
    pocz=pom;
}

ListaOkienEl* ListaOkien::WezPocz(){
    return pocz;
}

//definition of the class Window
class Okno {
protected:    
    int x1,y1,x2,y2;
    string nazwa;

public: 
    virtual ~Okno(){};  
    virtual ListaOkien* DajKontrolki(){return NULL;} //returns a list of controls if the window has them, otherwise returns NULL
    string DajNazwe() {return nazwa;}
    virtual Okno* DajOjca(){return NULL;} //returns the father of the window if it has a father
    virtual ListaOkien* DajPodokna(){return NULL;}        //returns a list of sub-windows if the window has them, otherwise returns NULL
    virtual ListaOkien* DajZminimalizowane(){return NULL;} //same with a list of minimalized subwindows
};
//here's how the controls are created (controls are windows as well)
template <class T>
void OtworzKontrolke(Okno& _ojciec,int _x1,int _y1,int _x2,int _y2,string _nazwa){
    cout<<"Jestem w OtworzKontrolke"<<endl;
    T* r = new T(_ojciec,_x1,_y1,_x2,_y2,_nazwa); //I don't give the constructor. It works fine, so why bother you?
    ListaOkienEl* p = new ListaOkienEl(*r);
    _ojciec.DajKontrolki()->DodajPocz(*p);
}

Edited 6 Years Ago by mmasny: n/a

This article has been dead for over six months. Start a new discussion instead.