Как работают счетчики, когда на класс ссылается другой класс и с геттерами - PullRequest
0 голосов
/ 19 декабря 2018

Описание проблемы

Я пытаюсь понять, как работают счетчики shared_ptr.В моем классе A, когда я использовал геттер, счетчик увеличивался на 1. При использовании экземпляра A в классе B счетчик увеличивался на 2. Когда я закончил с классом B, деструктор A позвонили дважды.

Что я не понял и что меня смутило, так это:

  • Почему счетчик A увеличился на 1, когда мы вызывали геттер a.a().Это потому, что мы вернули указатель с помощью функции «Копировать», поэтому теперь у нас есть 2 указателя, верно?

  • Почему у нас есть счетчик 3, когда вызывается дескриптор A?

  • В классе B почему счетчик увеличился на 2?

  • После окончания класса B как назывался деструктор A?

  • Когда я использую reset в обоих деструкторах, это становится страннее.


Исходный код

    #include <iostream>
    #include <memory>

    using namespace std;

    class A {
        public:
        A(int a):_a( make_shared<int>(a)) {cout <<"A constructor" << endl;}
        ~A(){/*_a.reset();*/cout <<"After destructor, number of As "<< _a.use_count() <<endl;}
        std::shared_ptr<int> a(){return _a;}
        //private:
         std::shared_ptr<int> _a;
    };

    class B {
        public:
        B(A a):_b( make_shared<A>(a)) {cout <<"B constructor" << endl;}
        ~B(){ /*_b.reset();*/ cout <<"After destructor, number of Bs "<< _b.use_count() << endl;}
         std::shared_ptr<A> b(){return _b;}
        private:
          std::shared_ptr<A> _b;
    };



    int main()
    {  
        int number = 10;
        A a(number);
        cout <<"counter of A is " << a._a.use_count() << endl;
        cout <<"counter of A is " << a.a().use_count() << endl;

        B b(a);
        cout <<"counter of A is " << a.a().use_count() << endl;
        cout <<"counter of B is " << b.b().use_count() << endl;

        return 0;
}

  A--->Number: Counter = 1
  B(constructor) pass A by value : counter = 2
  B--->Number: Counter = 3

Выход без сброса

Конструктор
счетчик A равен 1
счетчик A равен 2
B конструктор
После деструктора число As 3
счетчик A равен 3
счетчик B равен 2
после деструктора число Bs 1
после деструктора число As 2
после деструктора число As 1

Выход со сбросом

Конструктор
Счетчик A равен 1
Счетчик A равен 2
B Конструктор
После деструктора число As 0
СчетчикA - 3
, счетчик B - 2
После деструктора - число As 0
После деструктора - число Bs 0
После деструктора - число As 0

1 Ответ

0 голосов
/ 19 декабря 2018

Быстрый ответ

  • Каждый раз, когда вы звоните a.a(), он возвращает новый общий указатель на ресурсы.Первая - это переменная-член.Они в конечном итоге освобождаются, но нет никаких гарантий, так как вы не сохраняете возвращенный общий указатель в переменную (которая свяжет его с областью видимости).
  • Первый After destructor, ... - это потому что вы копируете значение A a в конструктор B. Если вы хотите избежать копирования, используйте ссылку B(A& a).
  • Число 3 из-за трех указателей shared_, внутреннего A a, возвращенного, но не освобожденного a.a() результат И копия A a, переданная в конструктор B.
  • В классе B вы также возвращаете новый общий указатель в b.b() -> счетчик приращения на единицу.

Я надеюсь, что это охватывает все ваши вопросы, я могу попытаться уточнить, если у вас есть какие-либо вопросы.

...