From 0af39ea9ef297bfbe87b6c12fd72432a06945637 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Tue, 30 Jun 2009 06:13:23 +0000 Subject: [PATCH] add a note about re-evaluating end() every time through a loop. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@74511 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/CodingStandards.html | 63 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/docs/CodingStandards.html b/docs/CodingStandards.html index b1199778b0f..84503ca6795 100644 --- a/docs/CodingStandards.html +++ b/docs/CodingStandards.html @@ -50,6 +50,8 @@
  • Do not use 'using namespace std'
  • Provide a virtual method anchor for classes in headers
  • +
  • Don't evaluate end() every time through a + loop
  • Prefer Preincrement
  • Avoid std::endl
  • @@ -661,6 +663,67 @@ increasing link times.

    + +
    + Don't evaluate end() every time through a loop +
    + +
    + +

    Because C++ doesn't have a standard "foreach" loop (though it can be emulated +with macros and may be coming in C++'0x) we end up writing a lot of loops that +manually iterate from begin to end on a variety of containers or through other +data structures. One common mistake is to write a loop in this style:

    + +
    +
    +  BasicBlock *BB = ...
    +  for (BasicBlock::iterator I = BB->begin(); I != BB->end(); ++I)
    +     ... use I ...
    +
    +
    + +

    The problem with this construct is that it evaluates "BB->end()" +every time through the loop. Instead of writing the loop like this, we strongly +prefer loops to be written so that they evaluate it once before the loop starts. +A convenient way to do this is like so:

    + +
    +
    +  BasicBlock *BB = ...
    +  for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I)
    +     ... use I ...
    +
    +
    + +

    The observant may quickly point out that these two loops may have different +semantics: if the container (a basic block in this case) is being mutated, then +"BB->end()" may change its value every time through the loop and the +second loop may not in fact be correct. If you actually do depend on this +behavior, please write the loop in the second form and add a comment indicating +that you did it intentionally.

    + +

    Why do we prefer the second form (when correct)? Writing the loop in the +first form has two problems: First it may be less efficient than evaluating it +at the start of the loop. In this case, the cost is probably minor: a few extra +loads every time through the loop. However, if the base expression is more +complex, then the cost can rise quickly. I've seen loops where the end +expression was actually something like: "SomeMap[x]->end()" and map +lookups really aren't cheap. By writing it in the first form consistently, you +eliminate the issue entirely and don't even have to think about it.

    + +

    The second (even bigger) issue is that writing the loop in the second form +hints to the reader that the loop is mutating the container (a fact that a +comment would handily confirm!). If you write the loop in the second form, it +is immediately obvious without even looking at the body of the loop that the +container isn't being modified, which makes it easier to read the code and +understand what it does.

    + +

    While the second form of the loop is a few extra keystrokes, we do strongly +prefer it.

    + +
    +