这是一个古老的,已回答的问题,但是@Alexandre问“为什么有人要这样做?”,我想我可以提供一个今天下午正在考虑的用法示例。
旧版代码。在末尾使用裸指针Obj * obj。
不幸的是,我有时需要(而不是经常)使对象存活更长的时间。
我正在考虑使其成为参考计数的智能指针。但是,如果我要在任何地方使用,都会有很多代码需要更改ref_cnt_ptr<Obj>
。如果将裸对象Obj *和ref_cnt_ptr混合使用,即使最后一个ref_cnt_ptr消失了,您也可以隐式删除对象,即使还有Obj *仍然存在。
所以我在考虑创建一个explicit_delete_ref_cnt_ptr。即引用计数的指针,其中仅在显式删除例程中进行删除。在现有代码知道对象生命周期的地方以及在我的新代码中使用它可以使对象存活更长的时间。
在对explicit_delete_ref_cnt_ptr进行操纵时,递增和递减引用计数。
但是,当在explicit_delete_ref_cnt_ptr析构函数中将参考计数视为零时,则不能释放。
仅当在类似删除的显式操作中看到参考计数为零时才释放。例如:
template<typename T> class explicit_delete_ref_cnt_ptr {
private:
T* ptr;
int rc;
...
public:
void delete_if_rc0() {
if( this->ptr ) {
this->rc--;
if( this->rc == 0 ) {
delete this->ptr;
}
this->ptr = 0;
}
}
};
好,像这样 引用计数的指针类型没有自动删除rc'ed ptr析构函数中指向的对象是有点不寻常的。但是似乎这样会使混合裸指针和rc'ed指针更加安全。
但是到目前为止,不需要删除它。
但是后来我想到了:如果指向的对象pointee知道该对象正在被引用计数,例如,如果该计数位于对象内部(或其他表中),则例程delete_if_rc0可以是指针对象,而不是(智能)指针。
class Pointee {
private:
int rc;
...
public:
void delete_if_rc0() {
this->rc--;
if( this->rc == 0 ) {
delete this;
}
}
}
};
实际上,它根本不需要是成员方法,而可以是一个自由函数:
map<void*,int> keepalive_map;
template<typename T>
void delete_if_rc0(T*ptr) {
void* tptr = (void*)ptr;
if( keepalive_map[tptr] == 1 ) {
delete ptr;
}
};
(顺便说一句,我知道代码不太正确-如果添加所有细节,它的可读性就会降低,所以我将其保留为这样。)
delete this
在类和用于创建该类对象的分配方法之间创建了紧密的耦合。这是非常糟糕的OO设计,因为OOP中最基本的事情是创建不知道或不在乎调用者正在做什么的自治类。因此,正确设计的类不应了解或关心它的分配方式。如果您出于某种原因需要这种特殊的机制,我认为更好的设计是在实际类周围使用包装器类,然后让包装器处理分配。