I can't see how this statement could possibly be true.
> no funny abstractions
Really? Maybe I suck at C++, but I can't meaningfully reason about template-heavy code. Not about the run-time performance, nor resource consumption. STL and Boost are beyond funny if you ask me.
> The formal standard defines what is undefined. Your safety-critical code shouldn't rely on some compiler-specific quirks or some magical code, but rather it should stay within the bounds of well-defined behavior.
Agreed. But take a look at the specification and you'll be amazed on just how much stuff is left for the actual implementation to figure out.
Which is why the coding standard for a critical project will disallow the use of things that can lead to undefined behavior.
This is not true, the two languages have diverged: http://en.wikipedia.org/wiki/Compatibility_of_C_and_C%2B%2B
C++ is a subset of C, not the other way around.
> the fact that they can interface with hardware at a fairly low level
That's certainly one reason. Others include raw performance (think real-time safety-critical applications), no funny abstractions, tighter memory footprint, more flexibility, etc.
> and the amount of engineers with C (and nowadays, C++)
While I believe there are a number of C++ engineers out there, I'd wager that the number of competent C language engineers has dwindled over the years. Sure, everyone learns some C, but to know it well enough to write embedded real-time safety-critical systems is a whole different game. (not to mention the number of Java engineers has greatly outpaced even C++ engineers, thanks to University teaching Java, Android's dominance, and the lower barrier to entry).
> The 'formal' standard doesn't help you much when there's so much undefined behavior.
The formal standard defines what is undefined. Your safety-critical code shouldn't rely on some compiler-specific quirks or some magical code, but rather it should stay within the bounds of well-defined behavior.