> A destructor can’t automatically handle the case where something doesn’t need to be cleaned up on an early return
It can. An object with destructor doing clean-up should be created only after such clean-up is needed. In case of a file, for example, a file object should be created at file opening, so that it can close the file in its destructor.
That’s fine when one wants to write a whole class for something. But sometimes a cleanup path is genuinely a one-off, and using something like defer is nice.