Jump to content

Two questions :: pre-post increment & top-down/bottom-up approach

- - - - -

This topic has been archived. This means that you cannot reply to this topic.
11 replies to this topic

#1
$AP

$AP

    Newbie

  • Members
  • PipPip
  • 24 posts
I have few questions ...

Q1. Why does pre-increment of a variable work faster than post-increment? If the statement is true, then why do we do use post increment while writing the code most of the time?

Q2. C is a top-down approach whereas C++ is a bottom-up approach. Now what does it actually mean?

Thanks in advance. :)

#2
sam961

sam961

    Newbie

  • Members
  • Pip
  • 1 posts
A1: The idea is a sense of programming...u can use pre-incremenet (for example in the loop ) and maybe the usage of post increment is most significant than the pre-increment ... u can say for ex : for(i=0;i<10;i++) similarly as for(i=0;i<11;++i)


A2:I dont know what u mean exactly...but this will be due to that C++ is update to C ...not all C++ programs can be written i C but the vice versa is true


#3
julmuri

julmuri

    Programmer

  • Members
  • PipPipPipPip
  • 139 posts

$AP said:

Q1. Why does pre-increment of a variable work faster than post-increment? If the statement is true, then why do we do use post increment while writing the code most of the time?

Consider this code:

	int a = 0;

	int b = i++;

	/* what happens is something similar to :

	int& operator++( int ) {

		int current;		// new copy is created


		current = *this;	// new copy is assigned

		// increment this


		return current;

	}

	*/


and :

	int a = 0;

	int b = ++i;

	/* what happens is something similar to :

	int& operator++( void ) {

		// increment this


		return *this;

	}

	*/


It should be pretty obivious :p

#4
WingedPanther

WingedPanther

    A spammer's worst nightmare

  • Moderators
  • 16,831 posts
2. You'll have to explain what you mean. I program the same way in both of them. They may encourage different styles of programming, but I'm not familiar with the terms "top down" and "bottom up" referring to a language, just a coding style.
Programming is a branch of mathematics.
My CodeCall Blog | My Personal Blog

#5
Lance

Lance

    Programming Professional

  • Members
  • PipPipPipPipPip
  • 276 posts

Quote

u can say for ex : for(i=0;i<10;i++) similarly as for(i=0;i<11;++i)

Wrong. In this case, post-inc and pre-inc makes no difference on the loop boundary. So you should write:
for(i=0;i<10;i++)
    do_something();
Or
for(i=0; i<10; ++i)
   do_something();

For builtin type, pre-inc and post-inc will result in same binary code for the previous two ways. C programs use both ways interchangably and they indeed are equivalent. However:
1. They are different if the value of the pre-inc and post-inc expression is used.
j = ++i; is not equivalent to j=i++;
j=*p++ is not equivalent to j=*++p;
assuming they are all valid expression and mean what they appear to mean.

2. You are told pre-inc could be more efficient than post-inc for a good reason when you're working on non-builtin types, eg. iterators, eg, you should use
for(std::vector<int>::iterator i=vi.begin(); i!=vi.end(); ++i)
{
     //...
}

Instead of,

for(std::vector<int>::iterator i=vi.begin(); i!=vi.end(); i++)
{
     //...
}

because they are equivalent function-wise but the latter is slightly less efficient.

Why? I guess Julmuri has already told you (or he meant to tell you but his code has a small defect, a reference to a local variable should not be returned)

Let's examine a typical implementation for a post-increment operator:
const foo foo::operator++(int)
{
      foo f(*this);  // make a copy of the value before increment\
      ++foo;         // call the pre-increment operator, 
                        // implementation of which skipped.
      return f;      // 
}
As we can tell from the above code, on top of the cost of pre-increment operator, calls to copy constructor are made 2 times. That is the difference people are talking about.

#6
Steve.L

Steve.L

    Programming Expert

  • Members
  • PipPipPipPipPipPip
  • 444 posts

$AP said:

I have few questions ...

Q1. Why does pre-increment of a variable work faster than post-increment? If the statement is true, then why do we do use post increment while writing the code most of the time?

Q2. C is a top-down approach whereas C++ is a bottom-up approach. Now what does it actually mean?

Thanks in advance. :)

First Question
Neither statement is technically faster. A pre-increment, such as ++i, will simply increment the variable before the whole of the line is computed, whereas a post-increment will increment the variable after the whole line is computed. For example:

// Assume a is 7 and b is 5, both integers.

int post = a++ - b;   // Here post would be 7 - 5 == 2, then a becomes 8.

// Assume a is 7 and b is 5, both integers.

int pre = ++a - b;   // Here pre would be 8 - 5 == 3, a became 8 first.


Second Question
Your statement is wrong, but I can explain what they are. ;)

Top-down programming means you start with high level material, and coding as if the low-level material (for example, some complex functions) have already been coded. Once done, you code the more complex material, repeating the process until you are done coding everything you have used. Bottom-up is the exact opposite approach; you code the complex functions and such first, then get higher and higher level until you get to your main implementation which should essentially use all the low-level code you have already pumped out. This is seen more frequently in object-oriented programming, and OOP is seen more frequently in C++ rather that C (no one likes to deal with structs when classes can be used and are more convenient). So your statement, although not correct, is generally true. You see bottom-up more often in C++ as opposed to C.

Hope this clears everything up, since the previous posts were somewhat unclear or just completely unhelpful (sam961's post was utterly useless and completely wrong).

#7
julmuri

julmuri

    Programmer

  • Members
  • PipPipPipPip
  • 139 posts

Steve.L said:

First Question
Neither statement is technically faster. A pre-increment, such as ++i, will simply increment the variable before the whole of the line is computed, whereas a post-increment will increment the variable after the whole line is computed.

Try to run this code :p


int __cdecl main( int argc, char** argv ) {

	std::vector<int>			vec;

	std::vector<int>::iterator		vec_iter;

	std::vector<int>::const_iterator	vec_end;

	clock_t					time;


	// push 10 000 000 items into our vector

	for ( int i = 0; i < 10000000; ++i ) {

		vec.push_back( i );

	} // for

	// save vector end to make looping faster :p

	vec_end = vec.end();


	time = std::clock();

	for ( vec_iter = vec.begin(); vec_iter != vec_end; ++vec_iter ) {

		// some operation here, we will just increment the value

		++(*vec_iter);

	} // for

	time = std::clock() - time;


	std::cout << "Pre increment time: "

		<< time

		<< std::endl;


	time = std::clock();

	for ( vec_iter = vec.begin(); vec_iter != vec_end; vec_iter++ ) {

		// some operation here, we will just the increment value

		++(*vec_iter);

	} // for

	time = std::clock() - time;

	std::cout << "Post increment time: "

		<< time

		<< std::endl;


	return 0;

} // main


Mine output:

Pre increment time: 2813

Post increment time: 17469


Like lance pointed out, it makes sense to use pre increment for non native types if you just need to increment it.

#8
Steve.L

Steve.L

    Programming Expert

  • Members
  • PipPipPipPipPipPip
  • 444 posts
Your test isn't completely valid. True, a pre-increment will run slightly faster than a post-increment in the general case, due to the fact that a temporary variable will be created in a post-increment to store the value before incrementing, however in a loop, the running time of incrementing a variable is insignificant compared to the running time of the body of the loop, and therefore both methods will yield the same running time. This has already been proven numerous times around the web, so I won't go into details. It can also be shown, in a similar test to yours (with optimization turned off), that post-increments will run more quickly than pre-increments. Funny, huh?

Don't try to prove running time by measuring, prove it in theory first. They will average out to be the same, however there are cases where pre is faster than post, and vice-versa. And in nearly every case, the difference is not enough that you will ever notice it.

#9
Lance

Lance

    Programming Professional

  • Members
  • PipPipPipPipPip
  • 276 posts

Quote

It can also be shown, in a similar test to yours (with optimization turned off), that post-increments will run more quickly than pre-increments.

I'd love to see an example. Do not put an idle loop in the pre-incrementor though.


For non-builtin types, post-increment is theoretically slightly slower than its pre-increment counterpart, even though the difference may hardly be noticeable.

The same holds true that a virtual function call will be slightly slower than its non-virtual counterpart because of the one extra level of indirection. You'll hardly notice that too but I am not aware of any C++ programmers who will blindly define all member functions as virtual. If you choose to program in C/C++, you basically manifest that you care about these little bits. True, many C++ programmers advocate std::string in favor of c style string, but there's a tradeoff. While in pre/post-increment case, there is no reasonable situation in which a post-increment will be faster than a pre-increment. A C++ programmer should form a habit of using pre-increment in situations where both are functionally equivalent.


A difference between post-increment and pre-increment operators(for non-build in type) is generally more significant than that between virtual and non-virtual function; think about the case when the class allocates memory dynamically or acquires resources in its copy contrustors.

Here is another example, what's so signifcantly different between ++i and i+=1 or even i=i+1? Why don't the language designers eliminate this language feature and stick to the more general form to make the language simpler? Because in C/C++, every little bit counts! That some practice is not practically significantly less efficient than another is not a good argument to say they are equal.


IMHO, Julmri's test is both relevant and valid.

Edited by Lance, 31 December 2008 - 05:39 PM.


#10
Steve.L

Steve.L

    Programming Expert

  • Members
  • PipPipPipPipPipPip
  • 444 posts
I found this page on the topic, it's pretty interesting. Both loops are exactly the same, minus the obvious pre- and post-increment difference.

Anyways, there's no use arguing over it, I'm just pointing out that, in practice, it generally doesn't matter which method you use.

#11
Lance

Lance

    Programming Professional

  • Members
  • PipPipPipPipPip
  • 276 posts
I checked that post. Here is my result. They generate identical assembly code, which agrees with my belief that post increment and pre increment are identidcal for builtin types.

test1.cpp
void func()
{
}

int main()
{
	int i;
	for(i=0; i<0x1000; ++i)
		func();		
}

test2.cpp
void func()
{
}

int main()
{
	int i;
	for(i=0; i<0x1000; i++)
		func();		
}

compile them with g++

g++ -O2 -S test1.cpp test2.cpp

And the generated assembly files are virtually identical(execpt the source file name). So it's been proven theoretically pre/post increment are identical. So I need to actually run it to know they are the same?

BTW, here is the assembly file
	.file	"test1.cpp"
	.text
	.align 2
	.p2align 4,,15
.globl _Z4funcv
	.type	_Z4funcv, @function
_Z4funcv:
.LFB2:
	pushl	%ebp
.LCFI0:
	movl	%esp, %ebp
.LCFI1:
	popl	%ebp
	ret
.LFE2:
	.size	_Z4funcv, .-_Z4funcv
.globl __gxx_personality_v0
	.align 2
	.p2align 4,,15
.globl main
	.type	main, @function
main:
.LFB3:
	leal	4(%esp), %ecx
.LCFI2:
	andl	$-16, %esp
	pushl	-4(%ecx)
.LCFI3:
	xorl	%eax, %eax
	pushl	%ebp
.LCFI4:
	movl	%esp, %ebp
.LCFI5:
	pushl	%ecx
.LCFI6:
	popl	%ecx
	popl	%ebp
	leal	-4(%ecx), %esp
	ret
.LFE3:
	.size	main, .-main
	.ident	"GCC: (GNU) 4.1.2 (Gentoo 4.1.2 p1.1)"
	.section	.note.GNU-stack,"",@progbits


#12
$AP

$AP

    Newbie

  • Members
  • PipPip
  • 24 posts
Thanks to all of you for the discussion.

I have a query on the second question.

Quote

Top-down programming means you start with high level material, and coding as if the low-level material (for example, some complex functions) have already been coded. Once done, you code the more complex material, repeating the process until you are done coding everything you have used. Bottom-up is the exact opposite approach; you code the complex functions and such first, then get higher and higher level until you get to your main implementation which should essentially use all the low-level code you have already pumped out. This is seen more frequently in object-oriented programming, and OOP is seen more frequently in C++ rather that C (no one likes to deal with structs when classes can be used and are more convenient). So your statement, although not correct, is generally true. You see bottom-up more often in C++ as opposed to C.

So, in bottom-up approach, we first do create the lower level functions which are implemented thereafter. So, if I make use of a structure in C, is this a bottom-up approach? Dont we use this method in procedural languages?