pre or post increment

Started by
10 comments, last by BoRReL 22 years, 6 months ago
Heya, I read the following in another post and can hardly believe it:
quote: 4. You should ALWAYS use the prefix increment when possible ... because the postfix increment has to make a copy ... and then increment the original. it++ is usually wrong or inefficient .. ++it is the correct way to do it ... as proof ... these lines: i = i + 1; i += 1; ++i; are all identical ... and generate identical code ... this one: i++ is NOT the same ... and is wrong for items without a copy constructor .. or wierd side effects.
Does VStdio''s optimizer not optimize this the proper way?? I don''t think for(i=0;i<10;i++) is slower than for(i=0;i<10;++i), is it? For now I only used the prefix notation with pointers. eg. ++dest = bla. Could somebody clear up my mind?? Gr, BoRReL
Advertisement
There are situations in which you particularly want postincrement, but in those cases where increment order is unimportant (like a for loop) use preincrement.

As for whether Visual Studio optimizes the for loop in question, it probably does since the order makes no difference. However, it doesn''t generally optimize your increment choices because it might damage your program logic.


To you it''s a Bently, to me it''s a blue car...
"Diddy"
P.Diddy
For integral types (like int) you won''t see any difference concerning the for loops. However if you use complex types (classes) the pre increment may be faster.
The only time it would ever matter is if you create your own class and overload the operators - AND it''s not true.

IF the post-incremet ++ calls the copy constructor, so will the pre - and ONLY IF you poorly implement the ++() operators.


  //No evil copy constructor calledconst CMyInt& operator ++()	{	++i;	return *this;	}  


Magmai Kai Holmlor
- Not For Rent
- The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
so should i start calling the programming language "++c"?

--- krez (krezisback@aol.com)
--- krez ([email="krez_AT_optonline_DOT_net"]krez_AT_optonline_DOT_net[/email])
I don''t know what you intendent to show Magmai Kai Holmlor.
The problem is not the constructor call. But when you are using a postfix operator you have to manipulate your object while you must return its old version.
By the way, your example is a pre increment, if i is a member.
To elaborate on what VolkerG said, consider the simple example below:
int i = rand() % 4000;int j = i++; 

What''s the value of j after the assignment? (It''s the original value of i). What''s the value of i? (It''s 1 greater than the original value). How did that happen? The preceding code is evaluated as
j = i;i = i + 1; 

In other words, j = i is equivalent to a copy constructor for more complex data types (operator= is often implemented as a copy constructor, right?) Compare that to the following:
int i = rand() % 4000;int j = ++i; 

In this case, j is assigned the value of i after i has been incremented . There''ll still be a copy, but two values aren''t returned (i++ includes an implicit return of i.)

Operator precedence and associativity can be some freaky stuff at times.
Magmai: Thats a prefix-increment operator you defined. Of course there's no need to call the copy constructor in that one, since it should always return a reference to itself. However, in a postfix increment you must return the object as it was before the increment was performed. Therefore you cannot return a reference to *this (assuming the operator actually modifies something). You must create a copy of the object, then perform the increment, and finally return the copy.

e.g.
      // a prefix increment similar to the one you showed above:CMyInt& CMyInt::operator ++(){   ++i;  // i is a member   return *this;}   // a corresponding postfix increment:CMyInt CMyInt::operator ++(int)   // the int makes it a postfix{   CMyInt tmp(*this);   ++i;   return tmp;}      

If you can write the postfix version without calling a copy constructor, then please show it.

[EDIT]
Thought about this some more:
Actually the postfix increment operator above uses two copy constructor calls, one to create tmp, and one to copy tmp to the anonymous 'return variable' (perhaps an optimizing compiler can eliminate one of them). Both calls can be avoided by writing a specialized constructor, but then you still get one constructor call (and the code is slightly 'messier'). I don't think it's possible to write a post-increment without calling at least one constructor (assuming you want it to behave similarly to the post-increment for built-in types).
[/EDIT]

Edited by - Dactylos on October 22, 2001 5:09:25 PM
What a pos. The overidden operator ++(int) doesn't get called at the same time the native post-inc op does!!! Is this the way it's suppose to work, or is MSVC6 broken? Any standards gurus?

So it only matters if you overload the post-fix operator. For native types the post-fix operator doesn't get called until _after the line it's on finishes executing, even if there's a pile of them on that line. With classes post-fix is called inline on MSVC6, and my stance is that VC6 is thus broken, and/or the C++ is bad if that's the way it's suppose to happen. It means you can't make a class work like a built in type, it's impossible due to the "int q" situation below.

Observe:
    #include < iostream.h > #include < conio.h > class CMyInt	{	public:		CMyInt() : i(0)			{}		CMyInt(const CMyInt& x)			{			cout<<"Evil Copy Constructor"<<endl;			i = x.i;			}				//Broken post-fix		CMyInt& operator ++(int)			{			i++;			return(*this);			}				operator int()			{			cout<<"int operator"<<endl;			return(i);			}						int i;	};int main(int argc, char* argv[])	{	CMyInt my;	int m=0;	int i=0;	int j=0;	int q=0;			cout<<"i="<<i<<endl<<"j="<<j<<endl;	i = j++;	cout<<"i="<<i<<endl<<"j="<<j<<endl;		cout<<endl<<endl;	cout<<"m="<<m<<endl<<"my.i="<<my.i<<endl;	m = my++;	cout<<"m="<<m<<endl<<"my.i="<<my.i<<endl;		cout<<endl<<endl;	cout<<"i="<<i<<endl<<"q="<<q<<endl;	q = i++, i++, i++;	cout<<"i="<<i<<endl<<"q="<<q<<endl;	getch();	return 0;	}    


Magmai Kai Holmlor
- Not For Rent

Edited by - Magmai Kai Holmlor on October 22, 2001 7:45:25 PM
- The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
quote:Original post by Magmai Kai Holmlor
So it only matters if you overload the post-fix operator. For native types the post-fix operator doesn''t get called until _after the line it''s on finishes executing, even if there''s a pile of them on that line.


Actually, I''ve wondered about this a number of times. I''m convinced that the postfix increment operator gets called after the statement, which may not correlate to the line. ie,
int i = 1;int a = i++ + ++i; 

has some interesting behavior. a probably ends up as 3, and so does i. (i++) is evaluated after the statement i + d, where d = ++i = 2. So a = 1 + 2, then i = 2 + 1.

Fascinating, isn''t it?

This topic is closed to new replies.

Advertisement