Chandler Bing Chandler Bing - 1 month ago 17
C++ Question

C++ - Basic garbage collector using reference counting

Ok, I'm trying to implement a garbage collector in C++ (a very basic one) using the concept of reference counting, and it works but there is something that I don't understand.

I have two classes:


  • a class called GC, basically what it does is just incrementing and decrementing the reference counter


  • a class named TObject which plays the role of a smart pointer(I overloaded the * and -> operators, and also the = operator)

  • Here is the code below:
    GC.cpp

    #include <iostream>

    using namespace std;

    class GC {
    public:
    GC(){
    this->refCount = 0;//Initialisation du compteur à zero
    }

    void incrementRef(){
    this->refCount++;//Incrémentation du compteur de references
    }

    int decrementRef(){
    return this->refCount--;//Décrementation du compteur de references
    }

    int getCounter(){//Getter du compteur de references
    return refCount;
    }
    ~GC(){}

    private:
    int refCount; //Compteur de references
    };


    TObject.cpp:

    #include <iostream>
    #include "GC.cpp"

    using namespace std;

    template <class T>
    class TObject {

    T *p;
    GC *gc;

    public:
    TObject(T *p){//Constructeur de recopie
    cout<<"refobject"<<endl;
    this->p = p;
    gc = new GC();
    this->gc->incrementRef();
    }

    virtual ~TObject(){//Destructeur
    cout<<"delete TObject"<<endl;
    if(this->gc->decrementRef() == 0){
    delete p;
    delete gc;
    }
    }

    T* operator->(){//Surcharge de l'opérateur d'indirection
    return p;
    }

    T& operator*() const {//Surchage de l'opérateur
    return *p;
    }

    TObject<T>& operator=(const TObject<T> &t){
    if(this->gc->decrementRef() == 0){
    delete p;
    delete gc;
    }
    this->p = t.p;
    this->gc = t.gc;
    this->gc->incrementRef();
    return *this;
    }

    GC getGC(){
    return *gc;
    }
    };


    And here how I tested it in main:

    TObject<int> t(new int(2));
    cout<<"t1 counter: "<<t.getGC().getCounter()<<endl;//Displays 1
    TObject<int> t2(NULL);
    cout<<"t2 counter: "<<t2.getGC().getCounter()<<endl;//Displays 1
    t2 = t;
    cout<<"t1 counter: "<<t.getGC().getCounter()<<endl;//Displays 2, why?
    cout<<"t2 counter: "<<t2.getGC().getCounter()<<endl;//Displays 2


    I don't get it, I copied t in t2 and I did not update t1! Why its reference counter was updated too?

    Answer

    It's because, both t and t2 are sharing same gc instance. Look at your overloaded = operator method :-

    TObject<T>& operator=(const TObject<T> &t)
    {
       if(this->gc->decrementRef() == 0)
       {
            delete p;
            delete gc;
       }
       this->p = t.p;
       this->gc = t.gc;  // you are using same gc. Instead, you must be using
                         //  this->gc = new GC(); 
       this->gc->incrementRef();
       return *this;
    }