2

Хорошо, я пытаюсь реализовать сборщик мусора на C++ (очень простой), используя концепцию подсчета ссылок, и он работает, но есть что-то, что я не понимаю ,
У меня есть два класса:
C++ - Основной сборщик мусора, использующий подсчет ссылок

  • класс под названием GC, в основном то, что он делает только приращение и декремент счетчика ссылка
  • класса с именем TObject, который играет роль интеллектуального указателя (я перегружен * и -> операторы, а также оператор =)
  • Вот код ниже: 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){ 
         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; 
        } 
    }; 
    

    А вот как я тестировал его в основной:

    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 
    

    Я не понимаю, я скопировал т в t2, и я не обновлял t1! Почему его счетчик ссылок также был обновлен?

    +1

    Знаете ли вы, что у нас уже есть 'std :: shared_ptr' для справки о подсчете памяти/времени жизни? –

    +0

    Да, но просто хочу знать, как это работает –

    +0

    Вам нужно прочитать [Как отлаживать небольшие программы] {https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) по Эрик Липперт, чтобы ответить на это сам. –

    ответ

    2

    Это потому, что и t, и t2 используют один и тот же экземпляр gc. Посмотрите на свой метод overloaded =:

    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; 
    } 
    
    +0

    Да, вы правы, спасибо! И что вы думаете об этой программе? это правильно? –

    +0

    На самом деле, как вы реализуете gc, я думаю, вы должны ожидать 2 как счетчик ссылок, когда t2 назначен t. Во всяком случае, я дал вам решение, почему вы получаете 2? –

    +0

    Да, это было решение, но я его обманул, и я понял, что должен пройти тот же самый gc, потому что оба они указывают на один и тот же объект! –

    Смежные вопросы