Rather than saying "foreach reads everything into memory first," it's more accurate to say that the
operator behaves differently in scalar and list contexts. Scalar context returns the next line of the file - list context returns all of them.
When to call by reference, and when not, is a little complicated, but a good rule of thumb is that if you're not absolutely sure what you're doing, you definitely shouldn't call by reference. If you are absolutely sure, you maybe still shouldn't.