I was getting through \"Exceptional C++\" by Herb Sutter lately, and I have serious doubts about a particular recommendation he gives in Item 6 - Temporary Objects.
He's right of course; calling end can instantiate and destroy a temporary object, which is generally bad.
Of course, the compiler can optimise this away in a lot of cases.
There is a better and more robust solution: encapsulate your loops.
The example you gave is in fact std::find, give or take the return value. Many other loops also have std algorithms, or at least something similar enough that you can adapt - my utility library has a transform_if implementation, for example.
So, hide loops in a function and take a const& to end. Same fix as your example, but much much cleaner.