intrusive_ptr is 32-bit; shared_ptr is at least 64-bit

First, remember a smart_ptr instance is a full-fledged object whose class often has methods or fields.

In contrast, a raw ptr instance is monolithic — not an instance of a class. Its pointee can often be an instance of a class with members, and you can access them like rawPtr->pointeeMethod2().

Since the counter is in the pointee object, an intrusive_ptr object needs no state. An intrusive_ptr do need methods. (Look, if a class has no, including inherited, field or method, then it’s useless.) Therefore, minimum members of an intrusive_ptr are

– internal pointer to the pointee object
– no other field
– ctor, dtor …
– no virtual functions

If an intrusive_ptr class uses no virtual function, then its size can be the size of the internal pointer, i.e. 32 bit, smaller than sizeof shared_ptr can’t. A shared_ptr object needs

– internal pointer to the pointee object
– some pointer that (indirectly) references the ref counter object somewhere in memory

Therefore, at least 64 bits, assuming a 32-bit machine.

intrusive_ptr and java interface

For a beginner to intrusive_ptr, we won’t be too far off to remember that a pointee class could (not required) implement a java-style interface with 2 public methods addRef and delRef(). The pointee class typically uses these methods to change a private field refCount.

In Boost, the intrusive_ptr actually uses 2 stipulated free functions, but they could (and often do) call methods of the pointee class, like our 2 methods.

##varieties of c++ variables — 4 dimensions

To understand the wide variety of C++ variables, consider…
— about the object —
1) Heap (=>pointer) ^ stack
2) Primitives ^ class types
— about the variable —
3) Pointer(and ref) ^ nonref types
4) locals ^ fields — globals are rare
First 3 dimensions make 8 types
* Pointer/ref to Heap primitive
* pointer/ref to Heap class type
* pointer/ref to anything on stack is questionable[1]
* class type on heap but not accessed by pointer? impossible
* class type on stack and not accessed by pointer
* primitive on heap but not accessed by pointer? impossible
* primitive on stack and not accessed by pointer

[1] but how about simple c-strings. I used many of them without malloc(). Some arrays do live on the stack!

Nonref types can be pbclone or pbref. Pointers should be passed as …pointers.

Vast majority of variables are local variables or fields. By default locals live on the stack, but a local ptr can point to a heap object. After out-of-scope, the heap leaks….;)

intrusive ptr — intrusive access to pointee state

Q: Why the world “intrusive” in intrusive_ptr?

A: because this pointer manipulates state of the pointee object. Typically the pointee object provides/allocates/embeds the ref counter. When an intr pointer joins the “club” of intr pointers, the pointer initiates a call[1] to increment the counter.

A: because the more common smart pointers don’t mess with the state of pointee object. Therefore, the intrusiveness is a defining characteristic of this type of pointer.

[1] intrusive_ptr_add_ref(). P33 [[beyond the c++ standard library]] says that ==often== this function calls a *member* method of the pointee class, in order to manipulate the counter *field*. I feel this is a common solution.

intrusive/shared_ptr — warrants/options/fan-club

a payload-class, or pointee-class or “managed-class” is fully aware of the intrusive_ptr instances, like a warrant, where the issuer (say IBM) is aware of how many warrants are out there.

a managed-class is unaware of the shared_ptr instances circling around like sharks (ready to KILL it), a bit like an option — IBM doesn’t know how many IBM options are out there.

shared_ptr is also like a Fan club for a celebrity — celebrity doesn’t know about the fans.

“Payload” is clearer in a phone conversation.

follow the vptr – RTTI (dynamic_cast, type_info…

This is yet another blog post on vtbl, RTTI, dynamic_cast, type_info…

We won’t be too far off if we imagine that all RTTI operations work their magic by following the vptr.

Remember each polymorphic class has a distinct vtbl. If there are 521 polymorphic classes in memory, then there are exactly that many v-tables in memory. Each polymorphic object holds a 32-bit vptr seated at the vtbl of the “real” class. Recall that during subclass instantiation, the vptr first gets seated at the parent vtbl, then reseated at the subclass vtbl.

Now you see that if there’s no virtual function among base and subclasses, then there’s no vtbl/vptr, and RTTI can’t “follow the vptr”.