Article by Ayman Alheraki on January 29 2026 06:04 AM
One of the most common conceptual mistakes—even among experienced developers—is treating a class as if it were something that exists in memory and therefore has an address that can be used like an object’s address. This misunderstanding triggers a chain reaction of confusion: pointers, references, object lifetime, parameter passing in C++, and even how Rust defines ownership and borrowing.
This article resets the discussion from first principles:
A class has no address. Only an object has an address.
Everything else follows logically from this fact.
In C++ (and most compiled languages), a class is a type. A type is a description or blueprint: it defines how an object would look in memory—its members, layout, offsets, methods, construction and destruction rules.
But a type itself is not instantiated at runtime.
class MyClass { ... };
→ a compile-time type definition
MyClass obj;
→ a runtime object creation
A type describes. An object exists. And only what exists can have an address.
This is why the phrase “address of a class” is meaningless in a memory-model sense.
What can exist:
The address of an object of that class
The address of a function
Metadata such as RTTI (indirectly), which is not an object instance you call methods on
An object receives an address because it occupies real storage. That storage may come from:
Automatic storage (stack)
Dynamic storage (heap via new)
Static storage (global or static variables)
In all cases, there is a concrete memory location.
A class, by contrast, is only used to define how that storage is interpreted when an object is created.
A pointer in C++ is a value that stores an address of something:
an object
a subobject
or a function
When you use pointers, what is really happening is simple:
an object exists
you take its address
you store that address in a pointer
You cannot access an object through a pointer until you dereference the pointer.
That is why:
p->member is shorthand for (*p).member
-> is not magic — it is dereference + member access
Pointers make no promises:
They may be nullptr
They may be dangling
They may point to invalid memory
And the program may still appear to work… until it doesn’t.
A C++ reference is not an independent object. It is an alias — another name for the same object.
Key properties:
It cannot be null
It must be initialized immediately
It cannot be reseated later
This is not syntactic sugar. It reflects a design contract:
A reference asserts that a valid object exists now.
That is why you use . with references: you are operating directly on the object, not through an address container.
You can create a reference from a pointer via dereferencing:
If the pointer refers to a valid object → the reference is valid
If the pointer is null or dangling → Undefined Behavior
References are not runtime safety mechanisms. They prevent null by design, but they do not prevent:
dangling references
references bound to objects whose lifetime has ended
A reference is a design guarantee, not a garbage collector.
Any professional discussion of pointers and references must answer three questions:
Ownership — Who owns the memory and is responsible for releasing it?
Access — Who may read or write it? (constness, concurrency)
Lifetime — When does the object begin and end its existence?
If you cannot answer all three for a pointer or reference, the issue is not “missing information” — it is a design flaw waiting to surface as a bug.
This is not about C++ syntax. It is about memory architecture.
C exposes pointers directly and trusts the programmer
C++ provides tools (RAII, smart pointers) to discipline pointer usage
Rust enforces ownership and borrowing rules at compile time
Yet the foundation is identical:
Objects exist
References and pointers relate to those objects
Lifetimes determine validity
Even high-level languages must confront these realities when dealing with FFI, buffers, performance-critical code, or systems programming.
A class is not an object. Only objects have addresses. Pointers hold addresses; references are aliases to live objects.
Those who understand this deeply:
write safer C++
understand why Rust is strict
and can debug the hardest memory bugs that syntax-level reasoning cannot explain
Those who don’t… end up fighting symptoms instead of understanding causes.