3

最常见的可重用引用计数对象使用私有继承来实现重用。我不是私有继承的忠实拥护者,我很好奇这是否是一种可以接受的处理方式:

class ReferenceCounter {
    std::size_t * referenceCount;
public:
    ReferenceCounter()
        : referenceCount(NULL) {};
    ReferenceCounter(ReferenceCounter& other)
        : referenceCount(other.referenceCount) {
            if (!referenceCount) {
                referenceCount = new std::size_t(1);
                other.referenceCount = referenceCount;
            } else {
                ++(*referenceCount);
            }
    };
    ReferenceCounter& operator=(const ReferenceCounter& other) {
            ReferenceCounter temp(other);
            swap(temp);
            return *this;
    };
    void swap(ReferenceCounter& other) {
        std::swap(referenceCount, other.referenceCount);
    };
    ~ReferenceCounter() {
        if (referenceCount) {
            if (!*referenceCount)
                delete referenceCount;
            else
                --(*referenceCount);

        }
    };
    operator bool() const {
        return referenceCount && (*referenceCount != 0);
    };
};

class SomeClientClass {
    HANDLE someHandleThingy;
    ReferenceCounter objectsStillActive;
public:
    SomeClientClass() {
        someHandleThingy = RegCreateKeyEx(...);
    }
    ~SomeClientClass() {
        if (objectsStillActive)
            return;
        RegCloseKey(someHandleThingy);
    };
};

或者我没有看到这个有微妙的问题?

编辑
我不是超级关心这个特定的实现(它可能有错误——在生产代码中使用类似的东西之前,我将花一些时间查看 shared_ptr 的内部)——我只是担心一般情况下可重用引用计数好东西似乎总是使用继承而不是组合来实现,这是有一个特定原因的。

4

3 回答 3

3

复制句柄的时候一定要记得复制计数器。您可能不希望将操作系统类型传递给模板,但我认为这里的安全性需要继承。(但不是继承自HANDLE。)

HANDLE也可能是一种特殊情况,因为它是 POD。本质上,您还有一个类型的指针,除了T*.

我看到了delete当计数变为零时你想要一些事情发生的动机。改编smart_ptr可能会奏效,而且您可能离这不远。

于 2010-04-15T01:53:08.250 回答
0

我不认为这有任何优点。引用计数只对共享对象有意义。目标是节省堆分配和/或这些的复制等。实际上,您实现了一种copy counter。但即使这样也没有用,因为它没有提供任何接口来查询计数器值。我可以建议重新访问boost::intrusive吗?

于 2010-04-15T02:08:30.610 回答
0

实际上,您正在为类HANDLE外部实现引用计数HANDLE......这该死的接近shared_ptr.

使用组合来实现引用计数很好,但如果您的引用计数对象ReferenceCounter拥有类HANDLE实例会更好......使用起来更安全,重用成本更低,因为您只实现一次删除例程而不是在其中执行你所有的构造函数(arg)。

使用私有继承的唯一正当理由是Empty Base Optimization,所有其他情况都可以处理组合,这在耦合方面要好得多,所以他们不太可能有充分的理由这样做,更有可能是出于误导或懒惰.

于 2010-04-15T06:40:38.640 回答