Как атомарные счетчики ссылок распространяются на все копии всего класса?

Я пытаюсь понять, как работает атомарный подсчет ссылок, но не могу понять, как счетчики ссылок распространяются на все копии экземпляра. На основании этого вопроса и ссылка на ускорение Я создал следующий код:

#include <atomic>
#include <iostream>
struct X {
    X() : ref_cout_(1){};
    mutable std::atomic<int> ref_cout_;
    X(const X* other) {
        other->ref_cout_.fetch_add(1, std::memory_order_relaxed);
    };
    ~X() {
        if (ref_cout_.fetch_sub(1) == 1) {
            std::cout << "relese main ressource " << std::endl;
        };
    }
    void print() { std::cout << ref_cout_.load() << std::endl; };
};

int main() {
    X* first = new X();
    X* second = new X(first); //ref count of first = 2; as expected
    X* third = new X(second);  // ref count does not seem to propagate to first
    first->print(); //prints :2. Strange
};

В приведенном выше коде счетчик ссылок first равен 1, затем 2 и еще 2. Я ожидал, что для правильной работы подсчета ссылок создание объекта third увеличит количество ссылок всех копий до трех. Отсюда у меня следующие вопросы:

  • Как я могу реализовать средство подсчета ссылок, которое увеличивает количество ссылок для всех копий?
  • Почему класс использует std::atomic<int> в качестве счетчика ссылок, а не `std::atomic‹int*›?

Буду благодарен за все подсказки и предложения!


person fabian    schedule 20.06.2021    source источник
comment
Этот mutable не нужен. std::atomic позаботится об этом.   -  person Pete Becker    schedule 20.06.2021
comment
Каждый объект имеет собственную копию ref_cout_, поэтому копирование second для создания third не влияет на first. Забудьте здесь atomic — это не влияет на то, что делает этот код. Если вам нужно обмениваться значениями между потоками, вам нужно делиться ими, а не делать отдельные копии.   -  person Pete Becker    schedule 20.06.2021
comment
mutable std::atomic<int> ref_cout_; наверное должно быть std::shared_ptr<std::atomic<int>> ref_cout_;. (И в этом есть доля иронии.)   -  person Eljay    schedule 20.06.2021
comment
@Элджей просто static std::atomic<int> ref_cout_; подойдет?   -  person Richard Critten    schedule 20.06.2021
comment
@RichardCritten • Возможно, в зависимости от варианта использования fabian.   -  person Eljay    schedule 20.06.2021
comment
На фундаментальном уровне подсчет ссылок работает иначе.   -  person Sam Varshavchik    schedule 20.06.2021