Zero-overhead abstractions

Why do many programming languages have null?

The usability of null

#include <iostream>

void foo(int* ptr) {
    std::cout << *ptr << std::endl;
}
int main() {
    int bar = 42;
    foo(&bar);
    foo(nullptr);
    return 0;
}

What could be improved?

Problems of null

  • null can mean multiple things: Not initialized, does not exist, not needed
  • For pointers, two things mix: Indirection with absence of a value
  • On the hardware level, null is a sentinel value (typically 0x0)
    • On some platforms, 0x0 might be a valid memory address!

Fixing it - v1?

struct MaybePtr {
    MaybePtr() : _exists(false) {}
    explicit MaybePtr(int* ptr): _ptr(ptr), _exists(true) {}

    int* get() const {
        if(!_exists) {
            throw std::expection("Value does not exist!");
        }
        return _ptr;
    }
private:
    int* _ptr;
    bool _exists;  
}
  • Not ideal:
    • Runtime error instead of compile time check
    • Some memory overhead

Zero-overhead abstraction

  • We want something like null with better ergonomics (i.e. an abstraction) but as efficient as a hand-written solution (i.e. if(!ptr))
  • Such abstractions (if they even exist) are called zero-overhead abstractions [Stroustrup, 2000]
  • Functions and local variables are zero-overhead abstractions!