what guarantees that the file is closed before the mutex is unlocked?
Because this is how C++ is designed: scoped objects (whatever the scope is: class, function, local block, ...) are destroyed in the reverse order in which they are initialized. There is really nothing more to say, it's just part of the spec.