An operating system can't just crash if memory allocation fails, because it's actually normal for the operating system to run out of memory. If your OS is even a little bit like Windows 95 or System V, it uses all of the "left-over" memory for the file system cache, so every time it tries to allocate memory, it probably needs to flush a page to disk, which takes long enough that the OS will also want to go back into the scheduler to try to find some more work to do while that runs.
Ironically enough, C++ has fallible allocation in the standard library in spite of being ill-suited for it (unless you have exceptions; those can support fallible allocation just fine), while Rust went with the let-it-crash approach in its standard library, despite the fact that the language itself allows you to just return an Option from all the functions that allocate memory.
>In RAII, holding a resource is a class invariant, and is tied to object lifetime: resource allocation (or acquisition) is done during object creation (specifically initialization), by the constructor, while resource deallocation (release) is done during object destruction (specifically finalization), by the destructor. Thus the resource is guaranteed to be held between when initialization finishes and finalization starts (holding the resources is a class invariant), and to be held only when the object is alive. Thus if there are no object leaks, there are no resource leaks.
All of this is violated if you are constructing objects in an 'invalid' state. The whole point of RAII is that you don't do this. If you have to check if the object is in an error state at the start of every method call, then you're not benefiting from RAII.
If you want to redefine things to be different just to win an argument, you can, but it's not something I'm going to continue entertaining as I'm pretty tired of it now.
And just because some low-level pointer primitive allows itself to have a null state doesn't mean your Files and DBConnections, etc., should have free reins to do the same.
I believe there are problems in the handling of exceptions in constructors and destructors, which permeates into other parts of the language such as how arrays are constructed, etc. For one, the only way a constructor can fail is through an exception, and that's pretty heavy-handed for a language which markets itself as "don't pay for what you don't use." So you can't do RAII in C++ without exception handling. (Note that Rust solves this by not even having constructors.)
There are also some problems with exceptions being slow code paths, but that probably varies by compiler.