The constructor of CLogger::ScopedReplacement does initialize g_Logger and the destructor resets it.
TestLogger, TestStdoutLogger and the new FileLogger store an object of that type alongside some additional data.
Previously g_Logger was reset to nullptr. Now it's reset to the previous CLogger (the nullLogger).
Now the CLogger is stored on the stack instead of dynamic memory.
The message "Engine exited successfully" might be logged even if an exception is thrown. That could be change using std::uncaught_exceptions.