通过组合来实现引用计数可以吗?
最常见的可重用引用计数对象使用私有继承来实现重用。我不是私有继承的忠实粉丝,我很好奇这是否是一种可以接受的处理方式:
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的内部结构)——我只是担心一般来说,有一个特定的原因可重用的引用计数好东西似乎总是使用继承而不是组合来实现。
Most common re-usable reference counted objects use private inheritance to implement re-use. I'm not a huge fan of private inheritance, and I'm curious if this is an acceptable way of handling things:
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);
};
};
or are there subtle problems with this I'm not seeing?
EDIT
I'm not super duper concerned with this particular implementation (it probably has bugs -- I'm going to spend some time looking at shared_ptr's innards before using something like this in production code) -- I'm just concerned if in general there is a specific reason reusable reference counting goodies always seem to be implemented using inheritance rather than composition.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
复制句柄时一定要记住复制计数器。您可能不希望将操作系统类型传递到模板中,但我认为这里的安全性需要继承。 (不过,不是从
HANDLE
继承。)HANDLE
也可能是一种特殊情况,因为它是 POD。本质上,您有一个除T*
之外的类型的指针。我看到了您希望在计数归零时发生除了删除之外的其他操作的动机。
smart_ptr
的改编可能会起作用,而且您可能离那不远了。You have to remember to copy the counter when copying the handle. You might prefer not to pass operating system types into templates, but I think safety here requires inheritance. (Not inheritance from
HANDLE
, though.)HANDLE
might also be something of a special case because it's POD. Essentially you have a pointer of type besidesT*
.I see the motivation that you want something besides
delete
to happen when the count goes to zero. An adaptation ofsmart_ptr
would probably work, and you might not be that far from just that.我不认为这有任何优点。引用计数仅对共享对象有意义。目标是节省堆分配和/或复制这些内容。事实上,您实现了某种复制计数器。但即使这样也没什么用,因为它不提供任何接口来查询计数器值。我可以建议重新访问
boost::intrusive
?I don't think this has any merit. Reference counting only makes sense for shared objects. The goal is to save on heap allocations and/or copying of these among other things. You, in fact, implemented sort of copy counter. But even that is not useful since it does not provide any interface to query the counter value. Might I suggest revisiting
boost::intrusive
?事实上,您正在为
HANDLE
类之外的HANDLE
实现引用计数...这非常接近shared_ptr
。使用组合来实现引用计数很好,但如果您的引用计数对象
ReferenceCounter
拥有类HANDLE
实例会更好...使用起来更安全,并且重用成本更低,因为您只实现一次删除例程,而不是在所有构造函数(arg)中执行它。使用私有继承的唯一有效原因是空基优化,所有其他情况都可以通过组合来处理,组合在耦合方面要好得多,因此他们不太可能有充分的理由这样做,更有可能的是,他们这样做是出于误导或懒惰。
You are in fact implementing reference counting for the
HANDLE
outside of theHANDLE
class... which is damn close to ashared_ptr
.Using composition for implementing reference counting is fine, though it would be better if your reference counting object
ReferenceCounter
was to own the classHANDLE
instance... Much safer in usage, and cheaper to reuse since you only implement the deletion routine once instead of doing it in all of your constructors (arg).The single valid reason for using private inheritance is
Empty Base Optimization
, all the other cases can be dealt with composition which is much better in terms of coupling, so it's unlikely that they have good reasons to do so, more probably they did it out of misguidance or laziness.