And they are indeed 16 and 12.
They are of this size, given:
- the compiler (& options) you used
- your target platform
- the absence of directives related to aligment/packing in the code
For your video, I guess the speaker just took a given platform/toolchain to develop his example. However in general, since sizeof(T)
is compiler/platform dependent, std::atomic<T>::is_lock_free()
is also compiler/platform dependent.
Examples
Using the following struct:
struct C {
uint64_t x;
uint32_t y;
};
Different compilers & options
Target platform
Alignment/packing directives
Why these differences ?
Compilers are free to add unused bits/bytes after any field of a structure/class. They do so for performance reasons: on some platforms, it is faster to read/write a multi-byte int
that verify certain alignment properties (usually, the address of a N
-bytes int
must be divisible by N
).
Usually, it's convenient that your C++ compiler performs low level optimizations behind your back. Sometimes you want more control on this feature (non-exhaustive list of reasons):
- when you serialize data which will be read by a different program (save to file, send to the network).
- when memory usage is more important than execution speed.
- in multicore & multithreaded program, controlling how many
struct
there are in a CPU cache line can limit cache invalidations between cores, which improves execution speed.
Which is why compilers usually provides utilities to control it.
TL;DR
The sizeof(T)
doesn't "have" to be anything for a given T
. It is compiler/platform dependent, and you can often override it with specific compiler directives.