Wednesday, August 03, 2005

Before, After - which one's better?

Its that time of the week again where I have the itching to post some C++ funda. The topic this time is "Pre-increment Vs Post-increment - Which is more efficient?".

One would not worry about this much in C. But in C++, one must. Why? Because, we have the possibility of user defined types coming into the language type system. Let me start with a simple example.


++i; // increment and return the value

i++; // copy initial value. increment. return the copy

Just by looking at the steps involved, can we not tell that pre-increment is more efficient? Not convinced? Okay, the "copy initial value" step would actually be a call to the copy constructor in case of a user-defined type. For example, for a hypothetical Integer class, I'll write the initial versions pre-increment and post-increment operators and point out problems and their fixes as I go.

Integer operator++() // pre-increment
{
   ++val_;
   return *this;
}

Integer operator++( int ) // post-increment
{
   Integer temp(*this);
   ++val_;
   return temp;
}

With these implementations - the following problems exist.

1.

Integer a = 10, b = 20;
++b = a;

The value of b would be 21 and not 10 as expected. To correct this, make the pre-increment operator++ return a reference to *this.

2.

Integer c(30);
c++++;

This works fine! But this is downright rubbish. To fix this, make post-increment operator++ return constant value.

3. This is a general guideline. Always implement post-increment in terms of pre-increment to be consistent.

Integer& operator++()  //point 1
{
   ++val_;
   return *this;
}

const Integer operator++( int )  //point 2
{
   Integer temp(*this);
   ++(*this);   //point 3
   return temp;
}

Hope it made sense! :D

7 comments:

  1. >> Just by looking at the steps involved, can we not tell that pre-increment is more efficient?

    Of course we can... ;-)

    Not convinced?
    Of course I am convinced :-D

    I have not read further, because I know you are going to prove this ;-)

    ReplyDelete
  2. y u always talk abt increment???
    talk abt decrement too :p
    dont gimme fundas now, abt optimism n positive thinking :p

    ReplyDelete
  3. sub0 - hey, there are some common pitfalls pointed out too...

    manu - yakappa?? i thot you were turning into a geek too! ;-)

    raju - whatever i said abt pre/post increment holds for pre/post decrement too. no - i'm not starting off with one more funda for a week now :P

    ReplyDelete
  4. :)..
    long lasting doubt clarified..

    ReplyDelete
  5. Here we go...

    I agree with Srinivas above, but the argument does not apply to primitive types (like int, char, etc...) which is where we use the post-increment and pre-increment the most.

    Most compilers produce *exactly* the same code for both the pre-increment and post-increment operators. Today's compilers are smart enough to make the distinction. For example, on the Sun java compiler :

    public class Test
    {
    public static void main(String args[])
    {
    int val = 5;
    int x, y;

    x = ++val;
    y = val ++;

    }
    };

    The corresponding byte code is:

    Code:
    0: aload_0
    1: invokespecial #1; //Method java/lang/Object."< init >":()V
    4: return

    public static void main(java.lang.String[]);
    Code:
    0: iconst_5
    1: istore_1
    2: iinc 1, 1
    5: iload_1
    6: istore_2
    7: iload_1
    8: iinc 1, 1
    11: istore_3
    12: return

    Look at lines 2 and 8 in the dissassembled Java byte code. They are exactly the same. The compiler was smart enough to figure out that it doesn't need a temporary place to store the post increment and converted it into a pre-increment

    This means that on primitive types (int, char etc...) both are exactly the same.

    ReplyDelete
  6. Well, please welcome the wizard - Mr. Aditya Pradip Kulkarni!!
    Yeah - what I wrote in the post is purely for user-defined types. And you always have to get into Java like I get into C++??

    ReplyDelete

What I want to say is: