
Overhead of counter and deleter is exactly the same for both shared_ptr and intrusive_ptr - one per object (the fact that intrusive_ptr doesn't support Deleter at the moment is beside the point IMO - it should). Slight difference is that former is require additional new call.
Additional new call is not very little thing. Extra heap operation have its cost. Not sure for other platforms, but with VS2005, new is roughly malloc, malloc is roughly HeapAlloc, and Windows heap have overhead like rounding up to multiply of 16 bytes per HeapAlloc and using additional 16 bytes per HeapAlloc. The reason for polymorphic deleter in shared_ptr is, IMHO, that additional heap object is allocated anyway, so here polymorphic deleter is almost free sugar. For unique_ptr deleter is non-polymorphic, unique_ptr does not need additional object by itself, so here polymorphic deleter would be an expensive thing. For intrusive_ptr polymorphic deleter is too expensive too. As for non-polymorphic - this can be controlled by intrusive_ptr_add_ref implementation. Also, there's an alternative for custom non-polymorphic deleter: member operator delete. For PODs or not editable classes it cannot be added, but then inheritance from intrusive_pointee_base cannot be added too. If class is yours, why not write operator new/operator delete for it ?