这是一个古老的已回答问题,但@Alexandre 问道“为什么有人要这样做?”,我想我可以提供一个我今天下午正在考虑的示例用法。
遗留代码。使用裸指针 Obj*obj,最后带有一个 delete 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 指针更安全一些。
但到目前为止没有必要删除它。
但后来我突然想到:如果指向的对象(指针对象)知道它正在被引用计数,例如,如果计数在对象内部(或在某个其他表中),那么例程 delete_if_rc0 可能是pointee 对象,而不是(智能)指针。
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;
}
};
(顺便说一句,我知道代码不太正确——如果我添加所有细节,它的可读性就会降低,所以我就这样离开了。)