Если вы хотите отловить недопустимое использование библиотеки (пытаясь получить доступ к объектам, когда они были удалены), а также иметь высокопроизводительный API-интерфейс (без API-адресов weak_ptr и shared_ptr), вы можете рассмотреть возможность использования другой API для отладочных и не отладочных сборок.
Давайте для простоты предположим, что у вас есть только один класс объектов, которые вы выставляете; Назовите этот класс Object. Тип указателя, который вы возвращаете из API для доступа к внутренним объектам, определяется как:
#ifdef DEBUG
typedef ObjectPtrFacade ObjectPtr
#else
typedef Object * ObjectPtr;
#endif
Здесь фасад - это класс, который ты пишешь. Это работает примерно так:
class ObjectPtrFacade {
public:
ObjectPtrFacade(Object *o) : wptr(o) { }
// copy constructor and assignment here etc. (not written)
Object * operator -> () const { return access(); }
Object & operator * () const { return *access(); }
private:
Object * access() {
assert(wptr.use_count() > 0);
return (Object *)(wptr.lock());
}
weak_ptr<Object> wptr;
}
Таким образом, всякий раз, когда вы создаете отладочную сборку, вы используете специальный вид интеллектуального указателя, который до доступа к объекту утверждает, что его use_count () больше нуля, то есть объект еще существует. Если объект был освобожден, вы получите несостоявшееся утверждение, которое лучше, чем ссылка на нулевой указатель.
В общем, конечно, это так, что использование weak_ptr не помогает, если у вас есть «глупые» пользователи API, потому что они могут вызвать lock () и затем сделать ссылку на нулевой указатель после того, как weak_ptr вернет shared_ptr, пусто ...