you not going to like this answer, but Don't teach it!!
At least, don't teach it unless your teaching a 300-400 level course in college.
Most code optimization is very tiny benefit, especially since modern compilers are able to do many of the optimizations for you and it's entirely possible for someone to optimize wrongly an slow something down instead.
More importantly code optimization takes time and often leads to less readable code, which is bad. It's very rare that any optimization other then algorithmic (Big O level) ones will ever be needed, and code readability is a huge and important factor of every program. You don't want to teach students to sacrifice readable, maintainable, and testable code for theoretical optimizations that often will not have a noticeable impact on rate that the code runs. Leave that to be learned in upper level coding courses only after they are able to write solid readable code.
The only type of optimization I would every worry about teaching is Big O level algorithmic optimizations, and even then I probably wouldn't worry too much about that until their in 200 level college courses.
For low level courses I would demonstrate the difference between quick sort and some naive sort, to show algorithms can matter, and not much else. Maybe give a quick example of a nested loop being much slower then two non nested loops, but I would not be emphasizing writing code efficiently, only showing that efficiency concepts exist, it's up to later classes for students to understand and make efficiency decisions.
At 200 level courses I would start stressing how things could be optimized algorithmically to some degree. You would likely be teaching more about different container types, linked lists vs arrays vs hash maps, so just explaining these algorithms in a way that touches on why one would use one over the other is good. You will be teaching them how skilled programmers use tricks to gain efficiency benefits by demonstrating the common algorithms they cam up with, which is great. However, the emphasis now is less about coming up with great algorithms themselves, and mostly knowing that algorithm decisions can matter and they should be picking the best collection/tool for the job based off of it's algorithmic efficiency.
At 200 level you can also start to point out particularly horrible Big O mistakes. The most obvious example would be including a nested for loop that does not need to be nested. Telling your students "try not to have multiple loops inside each other if you can avoid it, especially not if each of them can be large" is okay at this level. Give an example of why nested loops can be absurdly slow and how you can avoid it is okay, often this can be tied in with picking the right tool for the job by showing how iterating over an array once with a precompute phase to put stuff in a hash map before a second iteration is faster then the nested loop, and look here is a demonstration of another reason to use a hash map.
at 300 level courses your ready for a course that focuses entirely on algorithms, this one course should explain Big O vs Big Omega etc, give means of measuring algorithmic complexity, and really hammer in that algorithms matter. From this point on always bring up algorithmic complexity and ways to make better algorithms, their ready to adjust for this. However, still be quick to point out when an optimization was needlessly complex.
Sometime around 300/400 level optimization considerations other then algorithmic can be tackled as well. I would suggest tying this in with study of the physical limitations of a computer though. When you study how memory actually works you can give an example of how, for example, ensuring you access data 'nearby' each other to avoid cache hits is useful.
At this level of class I suggest explaining how the computer works and how this affects optimization decisions. Then give them an 'unoptimized' piece of code and tell them to optimize it. Write some automated testing scripts that will run the same code 1000 times on a large sample size, compare wall clock before/after it's run, and figure out the average speed of the code, then tell them you want them to provide N boost to it's runtime.
I had one such project where I got something like a 25 x speed increase when doing math on a 3 dimensional cube where we had to consider the content of each 'touching' cube. The biggest increase was changing the logic to minimize cache hits, but things like loop unrolling and replacing methods with macros also came into play, these was using a C compiler with all optimizations disabled. It really helped to show how drastic optimization can be.
However, it's important to always stress readable code is most important and that premature optimization is bad, repeat constantly to only optimize proven slow points and to test your code to identify where the slowdowns occur before trying to optimize.
If your not teaching high level courses though, just don't do it. It's likely to lead to worse code most of the time and just adds an extra thing for students to learn and get confused about. Focus on their writing good maintainable code and only after they have mastered that should they worry about 'efficient' code.