Raymond Chen3 min readintermediate
Magic statics vs. std::call_once
Summary
Function‑local "magic" statics give you thread‑safe, one‑time init for static data, but they’re limited to static storage and shared across all instances. Use `std::call_once` (or a small `lazy<T>` wrapper) when you need per‑object lazy init or when the value isn’t a static. The post shows concrete code for both approaches, explains the pitfalls of using a static inside a member function, and ske…
- Magic statics are concise and thread‑safe, but only work for static objects and are shared across all calls.
- `std::call_once` lets you lazily initialize non‑static members per instance, avoiding the cross‑instance sharing bug.
- Encapsulating `std::call_once` in a `lazy<T>` type (using `std::optional` and a once_flag) provides a reusable on‑demand initializer.
- Singletons are often implemented with a function‑local static; the same pattern can be used for any one‑time init that is truly static.
Choosing the right lazy‑initialization primitive prevents subtle bugs where per‑object state is inadvertently shared, and it keeps initialization cost out of the hot path while remaining thread‑safe.
6/10



