-
-
Save dwilliamson/7768229 to your computer and use it in GitHub Desktop.
| // | |
| // Oh dear! | |
| // | |
| struct Container | |
| { | |
| Container(); | |
| ~Container(); | |
| struct DependentTypeA& a; | |
| struct DependentTypeB& b; | |
| }; | |
| struct DependentTypeA { }; | |
| struct DependentTypeB { }; | |
| Container::Container() | |
| : a(*(new DependentTypeA)) | |
| , b(*(new DependentTypeB)) | |
| { | |
| } | |
| Container::~Container() | |
| { | |
| delete &b; | |
| delete &a; | |
| } |
Missed this comment, sorry :)
The most basic statement about this is:
- The
Containerobject is never valid if eitheraorbare null. - For (whatever) reason, they need to be allocated external to the storage for Container.
C++ is hopeless at expressing this.
In each use of Container, either from with its own functions or externally, any use of pointer values should check for null (assuming you treat pointers as optionals and references as not). Given that Container can guarantee it's not properly constructed if either a or b fail to allocate, it's a cognitive waste to have to keep pointers around and maybe/maybe not check them for null.
Well usually reference should be enough to ensure that pointer is pointing to proper object. But still is not 100% safe as allocation can return 0. But probably new just throws exception, at least this should be a case for default CRT.
In general case references and pointers are the same, it is just a bit harder to assign zero pointer to reference.
Of course, they're the same... but working within the language semantics references are sometimes used to specify the intent that the object is always valid (allocated). Hardware exception handling can cover the rest, while spurious memory trampling highlights double-deletes or reuse of deleted pointers.
C++ lawyers love to tell you that "it's not possible to have a null reference" through circular reasoning:
- A: See 8.3.2! De-referencing a null pointer is undefined behaviour. After that your program is no longer well-defined so it is in fact impossible to have a null reference!
- B: But, look... here, in my debugger: a null reference! And I can't tell you where it comes from.
- A: Well, that's because your program is in an invalid state. If it wasn't in that state then the null reference wouldn't exist!
slowly walks away
Yikes, I would think that one would question whether a slight compile win is worth trading off runtime performance due to heap operation overhead. Probably not cheap unless you know for sure that DependentTypeA and DependentTypeB are pool allocated and have correctly overloaded new and delete. Also handling heap failures from inside the initializer list (and destructor) of another class sounds... challenging.