Skip to content

Instantly share code, notes, and snippets.

@dwilliamson
Created December 3, 2013 12:12
Show Gist options
  • Select an option

  • Save dwilliamson/7768229 to your computer and use it in GitHub Desktop.

Select an option

Save dwilliamson/7768229 to your computer and use it in GitHub Desktop.
Assuming all functions that receive a pointer must assert-check for null... Container can define members that are references, require no assert checks and yet don't require dependent types to be included at the point of definition.
//
// 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;
}
@gorlak

gorlak commented Sep 29, 2014

Copy link
Copy Markdown

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.

@dwilliamson

Copy link
Copy Markdown
Author

Missed this comment, sorry :)

The most basic statement about this is:

  • The Container object is never valid if either a or b are 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.

@sopyer

sopyer commented Oct 7, 2014

Copy link
Copy Markdown

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.

@dwilliamson

Copy link
Copy Markdown
Author

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment