为什么shared_ptr实现中的ref_count是int *

时间:2017-08-29 03:38:57

标签: c++ shared-ptr

我见过几个shared_ptr的实现,例如here。所有人都将ref_count声明为int*。如果只是int,我不明白我们会失去什么。谢谢!

template <class T>
class shared_ptr {
    T* ptr;
    int* ref_count;

    /**
     * Initializes the ref count used for tracking the usage.
     */
    void initialize_ref_count() {
        if (ref_count != nullptr)
            return;
        try {
            ref_count = new int;
            *ref_count = 1;
        }
        catch (std::bad_alloc& e) {
            std::cerr << "Memory allocation error: " << e.what();
        }
    }
}

2 个答案:

答案 0 :(得分:7)

正如您在提供的实现(in your link)中所看到的,当共享指针是复制构造复制分配时,指向引用的指针计数器(ref_count)在管理同一指针的所有实例之间共享

    // Copy constructor
    shared_ptr(const shared_ptr& copy) {
        ptr = copy.ptr;
        ref_count = copy.ref_count; // see here
        if (ref_count != nullptr) {
            ++(*ref_count);
        }
    }

    // Assignment operator
    shared_ptr& operator=(const shared_ptr& copy) {
        ptr = copy.ptr;
        ref_count = copy.ref_count; // see here
        if (ref_count != nullptr) {
            ++(*ref_count);
        }
        return *this;
}

通过这种方式,该共享指针的所有实例引用相同的内存位置来跟踪引用计数器,最后shared_ptr将能够知道它是否需要进行清理(delete分配的内存):

   ~shared_ptr() {
        --(*ref_count);
        if (*ref_count == 0) {
            delete ref_count;
            ref_count = nullptr;
            delete ptr;
            ptr = nullptr;
        }
    }

声明

这个答案基于OP为简单起见提供的示例。 shared_ptr实现比示例中的实现要复杂得多(考虑原子性,竞争条件等......)。

答案 1 :(得分:3)

首先,在其他人分享内容时,您需要将其放在其他人可以访问的地方。正如@Igor Tandetnik所说。因此,动态存储持续时间的对象可以很好地完成工作。具有动态初始化的静态存储持续时间的对象也可以这样做,但该对象将存在于程序的其余部分,这是我们不想要的。

其次, shared_ptr比那更复杂。典型的shared_ptr将引用控制块。此控制块通常包含:

  • 对象的共享引用数
  • 有问题的对象或指向对象的指针
  • 以及对控制块的弱引用数。

对于线程安全性,共享引用计数和弱引用计数通常由原子类型保存。

编辑:请参阅@Passer评论。