Raymond Chen2 min readintermediate
std::call_once vs. std::async
Summary
Raymond Chen compares using std::call_once versus std::async (deferred) for lazy initialization in C++. He shows that std::async can be wrapped in a shared_future for repeatable get() calls, but it adds heap allocation and extra code, while call_once is tiny; exception behavior also differs.
- Wrap a deferred std::async in a shared_future to allow multiple get() calls and cache the result.
- shared_future::get() is const and thread‑safe, returning a const reference to the cached value.
- std::call_once compiles to a pointer‑sized object, while std::future incurs heap allocation and pulls in thread library code.
- Exception safety differs: some std::call_once implementations are not exception‑safe, unlike std::async’s handling.
C++ engineers implementing thread‑safe lazy initialization need to understand the performance and safety trade‑offs between call_once and async.
6/10


