In the first loop, you construct and destroy the ofstream
each time through the loop. The constructor opens the file; the destructor flushes the buffer and closes the file. These operations are not cheap.
In the second loop, you construct the ofstream
once, use that one object through all iterations of the loop, then destroy it once (when it goes out of scope later). You only open the file once and you only close the file once.
The compiler cannot transform the first loop into the second (or vice-versa) because they are not equivalent: opening and closing files are actions that have external effects.
In general, yes, you should always declare objects with as limited a scope as possible. But there are limits to this--when construction or destuction is expensive, you should avoid constructing more objects than you need to.