Is C++ really that bad?

Well... yeah. Take this:

void foo() {
    T* t = new T();
    t->bar();
    delete t;
}

If T::bar throws, then sizeof(T) is leaked. Instead, we need this - assuming T::bar only throws something derived from std::exception:

void foo() {
    T* t = new T();
    try {
        t->bar();
    } catch(std::exception&) {
        delete t;
        throw;
    }
    delete t;
}

Now when we have two raw pointers to heap allocated memory that we're responsible for, the interactions get much worse. Luckily std::unique_ptr solves all this, as if t->bar() throws then std::unique_ptr's destructor is called which calls delete t for us, hence both delete t lines are not needed and because we only catch an exception to throw it back, the try/catch block is not needed either thus reducing it to void foo() { std::unique_ptr<T> t(new T()); t->bar(); } and now we're protected against memory leaks.

There is still the issue of what happens if new T() throws, though... if it's a std::bad_alloc then no memory was actually allocated, but we're also effectively out of memory so that's not good. But if T::T() throws then the constructor is aborted and the destructor is not invoked, however the memory for the T itself is released and the destructor of each fully-constructed member is executed. Hence any T that calls new in the constructor and stores the result in a raw pointer will cause a memory leak for those dynamically allocated members. Which really means that classes should not have any raw pointers and should only have std::unique_ptr members if it needs some sort of dynamically allocated (possibly polymorphic) or optional member. The alternative is much much worse:

T::T() try : u(nullptr) {
    U* u = new U(/* args */);
    /* stuff */
} catch(/* something */) {
   delete /* raw ptr */;
} // implicitly rethrows
/r/cpp Thread