The easiest path in C++ is almost always the dangerous path. (The classic example is operator[] versus at().) With every tiny feature of the language, things we take fully for granted in every other language, there is a host of caveats, gotchas, footguns, and trap doors.
This is as serious risk as a project and its team grows, because the accumulated sum of accidental complexity grows exponentially.
It’s possible to manage this risk, but it is also expensive, and every modern-ish competitor to C++ allows fewer people to deliver better software quicker.
It’s not a good choice for almost anything that doesn’t specifically require C++ for its own sake.
If you use warnings as errors they catch even subsets of dangling nowadays. Other ways of dangling have been made illegal (temporary conversions and range for lifetime extension).
I agree with you the defaults are still not the best but it is dteafily getting better.
But I think in the next years things are going to be tightened further in standard terms for better defaults. In fact, it is already happening.
The difficult part I think it is lifetimes.
Lifetimes are a crucial aspect of writing code in C++, yet they do not appear anywhere in the syntax. The same goes for synchronization. These problems are fundamentally unfixable without major, incompatible language changes.