I have no constructor, and I must initialize
C++’s object initialization rules and “special member functions” draw sharp criticism for their complexity and potential for subtle bugs, especially around default constructors, zero-initialization, and partially constructed objects. Commenters contrast this with languages like Rust, Go, and Java, which either avoid special constructors or treat them more simply, arguing that this reduces footguns and cognitive load, particularly for large teams and junior engineers. Others defend C++ as a powerful, performance-oriented, multi-paradigm tool whose complexity is manageable with discipline, style guides, and modern best practices such as the “rule of zero/five” and heavy use of static analysis.
C++ Initialization and Constructors Complexity
- Many commenters describe C++’s initialization rules (default/value/list/aggregate, special member functions) as excessively complex and surprising, especially around defaulted constructors and subtle UB.
- Others argue this is mostly about rare corner cases; typical code uses a small subset and works fine, especially with guidelines (rule of 0/3/5, RAII, no globals).
- Some think the article’s advice “always write your own constructors” is itself bad; core guidelines prefer relying on generated operations when feasible.
Comparisons to Java, Rust, and Go
- Java constructors are seen by some as relatively simple; others list serious pitfalls: partially constructed objects leaking, exceptions during construction, ordering rules with super(), field initialization, and “don’t call overridable methods in constructors.”
- Rust and Go avoid “special” constructors: you use regular functions/factory methods and struct literals. Many find this simpler and more predictable.
- However, there are complaints that Rust lacks ergonomic, guaranteed placement-new–style initialization and precise control over stack vs heap usage.
- Go’s universal zero-initialization is praised for simplicity but criticized for enabling bugs when new fields are added and not explicitly set.
Footguns, Undefined Behavior, and Tradeoffs
- Strong theme: C++ has many “footguns” (patterns that look natural but are dangerous), often tied to UB and optimization (e.g., null pointer assumptions, type punning, initialization order, static objects).
- Some argue experts can avoid these and C++ then works well; critics respond that accidental misuse is exactly what makes them problematic.
Language Size, Subsets, and Style Guides
- Several note the C++ spec’s huge size and depth of interactions as beyond what most humans can fully master.
- Large organizations enforce strict subsets (e.g., bans on exceptions, RTTI, certain std libs) via style guides and tooling to keep code understandable and safe.
- There’s discussion of whether C++ should adopt Rust-like editions or more aggressively remove legacy features; others say ABI, tooling, and backwards-compat constraints make this hard.
Patterns, Best Practices, and Pitfalls
- Recurrent advice: avoid const references as data members; use wrappers if you must store references.
- Avoid static/global initialization order dependence.
- Prefer explicit initialization everywhere; don’t rely on tricky default or list-initialization behaviors.
Miscellaneous
- People share tools for demystifying implicit behavior (cppinsights, Godbolt).
- The blog’s title and retro theme get praise, as does the article as an interview question source.