When you construct an object, you allocate memory. For example, T foo; allocates memory sufficient for type T.
In your mental model, associate the block of memory where foo sits with T.
The essense to be safe is:
If a block of memory has type T, you may only use:
- [
const/volatile]T*pointer - a [
unsigned]char*pointer - a
U*pointer whereUis a unionunion U { T t; /* ... */ }; - a
P*pointer wherePis a type related toT(e.g. base class:struct T : P { /* ... */ })
to refer to it.
There are some other acceptable pointers but the above would cover most cases one would want.
This is why you shouldn't do char buffer[100]; T* t = &buffer; because buffer is char, not T.
This is also why T t; char* u8ptr = &t; is safe.