C++'s `noexcept` can sometimes help or hurt performance
Deterministic randomness & standard-library portability
- Several comments focus on
std::uniform_int_distributionbeing implementation-defined across libraries, breaking deterministic tests and fuzzing. - Some see this as a major flaw: a “standard” library that behaves differently per platform is called “absurd” and “under/over-specified.”
- Others defend the choice: different architectures (CPUs, GPUs) need different algorithms; over-specifying implementations (as with
std::regexand standard hash tables) is blamed for bad performance. - Suggested workaround: use Boost or other libraries when reproducible randomness is required.
Spec vs single reference implementation
- One camp argues the C++ committee should ship code (a single stdlib implementation) instead of a spec, citing Rust’s approach and faster evolution.
- The opposing camp sees a spec as a long-term strength: cross-vendor experimentation, platform-specific optimizations, and lessons feeding back into the standard.
- Disagreement on whether multiple “real” standard library implementations meaningfully exist; many cited alternatives (EASTL, HPX, Abseil, Folly, libcu++) are partial or non-
std::-namespace.
What noexcept actually does
- Clarified that
noexceptdoes not statically forbid throwing; it instead guarantees that if an exception escapes,std::terminateis called. - That guarantee must be implemented, adding metadata and complexity; some compilers historically inhibited inlining across
noexceptboundaries.
Performance: where noexcept helps
- Clear wins:
std::vectoruses move instead of copy only if moves arenoexcept, affecting reallocation cost.std::unordered_*may avoid storing hashes if the hash functor isnoexcept, reducing memory.
- On “zero-cost” EH platforms, normal execution pays almost no runtime cost;
noexceptmainly affects code size and certain optimization choices.
Performance: where noexcept can hurt or confuse
- Overusing
noexcept(marking functions that can throw) forces compilers to maintain termination paths and unwinding metadata, potentially bloating binaries or affecting inlining. - Some backend engineers argue
noexceptwas oversold as a free optimization; inlining with mixednoexcept/non-noexceptregions is especially tricky. - One proposed alternative (not adopted): make violations UB so compilers can treat
noexceptas a pure optimization hint.
Compiler analysis & checked-exception analogies
- Compilers can infer that some functions don’t throw, but cannot in general decide this for all call graphs.
- Some wished for Java-like checked exceptions or a stricter
noexceptthat only calls othernoexceptcode, but others note practical issues with C libraries and existing ecosystems.
Exceptions, tooling, and methodology
- Some projects simply compile with
-fno-exceptionsto avoid overhead and complexity. - Notes on implementation:
- Historical GCC unwinding used a global lock; newer work aims to scale better.
- On some platforms, overhead is mostly in unwind tables, not instruction cost.
- Several commenters criticize the article’s benchmarks:
- Example code sometimes shows identical assembly for
noexceptvs non-noexcept. - Timing methodology (choice of clock, lack of clear harness) is questioned.
- Example code sometimes shows identical assembly for
- General advice: use tools like Compiler Explorer to inspect codegen rather than relying on folklore about exceptions and
noexcept.