Это старый вопрос с ответом, но @Alexandre спросил «Зачем кому-то это делать?», И я подумал, что могу привести пример использования, которое я рассматриваю сегодня днем.
Устаревший код.Использует голые указатели Obj * obj с удалением obj в конце.
К сожалению, иногда мне нужно, но не часто, поддерживать объект дольше.
Я подумываю сделать его умным указателем с подсчетом ссылок.Но было бы много кода, чтобы измениться, если бы я должен был использовать ref_cnt_ptr<Obj>
везде.И если вы смешаете голый Obj * и ref_cnt_ptr, вы можете неявно удалить объект, когда последний ref_cnt_ptr исчезнет, хотя Obj * еще жив.
Так что я подумываю создать явный_delete_ref_cnt_ptr.Т.е. указатель с подсчетом ссылок, где удаление выполняется только в явной процедуре удаления.Использование его в одном месте, где существующий код знает время существования объекта, а также в моем новом коде, который поддерживает объект живым дольше.
Увеличивается и уменьшается счетчик ссылок как явный_delete_ref_cnt_ptr.*
Но НЕ освобождает, когда счетчик ссылок считается равным нулю в деструкторе clear_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'-указателей более безопасным.
Но пока нет необходимости удалять это.
Но тогда мне пришло в голову: если объектуказанный объект знает, что подсчитывается ссылка, например, если счетчик находится внутри объекта (или в какой-то другой таблице), тогда процедура 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;
}
};
(Кстати, я знаю, что код не совсемправильно - если я добавлю все детали, он станет менее читабельным, поэтому я оставлю это так.)