TIL-6
Why does calloc exist?
Explain the reasoning behind the calloc
function in C. The use of calloc
ensures the allocated memory is zeroed. Compared with the malloc
+ memset
method, calloc
offers overflow checking and is more efficient than the malloc
because it relies on the fact that 1) new memory returned from OS is zeroed and 2) the actual memory allocation (page fault) is delayed until the application starts to access the memory.
C++ Standard Parallelism

It reminds me of certain ways to implement an efficient wc
. Given a std::string content
,
- to count the number of chars, simply call
content.size()
; - to count the number of words, use the algorithm above;
- to count the number of lines, use
std::count
withpar_unseq
My mental model for
-
seq
: normal sequential program -
unseq
: SIMD instructions -
par
: multithreading -
par_unseq
: multithreading with SIMD instructions
Empty Base Optimization
Why Empty class requires to have one byte? It’s worth remembering that in C++, “the addresses of distinct objects of the same type are always distinct”.
- At first glance, it makes no sense that we can have two objects of the same type that are in the same address.
- But this rule is relaxed in C++20 to further promote EBO
When can we apply [[no_unique_address]]
? We use it typically when we need to put some empty class inside some classes.
EBO application: std::pair
(reduce the size of the pair), any allocator-awarded container (avoid some extra bytes caused by the storage of the allocator).
A corner case of EBO:
Empty base optimization is prohibited if one of the empty base classes is also the type or the base of the type of the first non-static data member, since the two base subobjects of the same type are required to have different addresses within the object representation of the most derived type.
Trivia
- Discussions about
TCP_NODELAY
- Pipe mechanism
- Pipeline as parallel command
- When the second application (receiver) exits while the first application (sender) still writes to the pipe, we get broken pipe (SIGPIPE)
- A typical example of SIGPIPE
- Recursive Lambda in C++
- The Surprising Costs of void() (and Other Not-Quite-Innocuous Evils)
- We cannot capture lambda itself when creating the lambda. Neither by value or by reference will work. By value definitely cannot work due to recursive definition. By reference has the potential to work, but as we cannot during the type of the lambda when capturing it, it doesn’t work.
- There are two solutions to build a recursive lambda. The first one is to take another
auto
parameter which we will use to accept lambda. The second one is to use declare a variable with typestd::function
, which allows us to capture this variable when declaring lambda (as shown in video). However, we need to take care of its lifetime as we are capturing by reference here.
- Why can’t variables be declared in a switch statement?
- Cases are just labels. (That’s why we could have tricks like Duff’s device).
- The best way to deal with them is to treat them as labels (like those in jump). We could avoid the uninitialization errors by using a
{}
bracket in each case (therefore, each case is not in the same scope).
- Rust reference
- Reference to a reference in Rust
- Deref trait and Deref coercion. If we are passing reference of references, it will be automatically coerced.
- Index trait and []
- The Blank Sheet
- Reading Better: Retaining and Applying What You Read
- Active reading.
- Inline namespace
- C++ Weekly - Ep 320 - Using
inline namespace
To Save Your ABI - How the object file is linked when we apply
inline namespace
: a call toA::f
is linked toA::inline_namespace_name::f
- Therefore, we could use different inline namespace names for different versions of our library. As a result of that, the ABI break will actually cause linker errors.
- C++ Weekly - Ep 320 - Using
- Order of destruction for stack/heap allocated arrays
- The array elements will be destructed in reverse order of construction, with element 99 being the first destructed, then element 98, 97, 96… etc. and element 0 being the last.
- It’s reasonable once you think about how we declare variables in program order like this:
A a; B b; C c;
. The construction order is A, B, C, and the destruction order is C, B, A. This corresponds to how the array is constructed/destructed.