Today, while reading the documentation for Google C + + programming style, 5.10. Pre-increment and self-subtraction: There is a sentence that caught my attention:
For iterators and other template objects use the prefix form (++i) for the self-increment, the decrement operator. The reason is that pre-increment (++i) is usually more efficient than post-increment (i++). So I checked the difference between front + + and post + + .
Note: "More effective C + +" clause 8 also specifically describes the problem. Later I found that the following article is basically a replica of it, haha
The difference between front + + and post + +
"c Expert Programming" has the following description (P276, people's post and Telecommunications publishing house):
++a means to take the address of a, add its contents, and then put the value in the Register;
a++ means taking the address of a, loading its value into the register, and then increasing the value of a in memory, (that is, the value of the register is used in the operation, i.e. the value before the increment)
In addition, I found an article on the internet, through the operator overload angle to explore their differences, as follows:
Suppose there is a class age, which describes ages. This class overloads the front + + and post + + two operators to achieve self-amplification of age.
classAge { Public: Age&operator++()//Front + + { ++i; return* This; } ConstAgeoperator++(int)//Rear-facing + +{age TMP= * This; ++(* This);//using pre-built + + returntmp; } Age&operator=(intI//Assignment Operation { This->i =i; return* This; } Private: inti; };
From the above code, we can see that the front + + and the Post + +, there are 3 points different:
- return type is different
- Different form parameters
- Code different
- Different efficiency
Differences in return value types
The return type of the predecessor + + is Age&, and the return type of Post + + is const age. This means that the front + + return is the left value, and the rear + + returns the right value. (There are a lot of discussions about Lvalue and rvalue, see below in this article)
The left and right values determine the usage of the front + + and the Post + +.
int Main () {Age A; (a+ +) + +; // Compile error + + (a++); // Compile error 1; // Compile error (++a) + +; // OK + + (++a); // OK 1; // OK }
The type of + + is a const age, and it is not possible to perform operations such as PRE + +, Post + +, and assignment.
++a type is age&, of course, it can be pre + +, Post + +, assignment and other operations
What is the return type of the a++ if it is a const object?
There are two reasons:
- If it is not a const object, an expression such as a (+ +) + + can be compiled. But the effect is a violation of our intuition . A actually adds only 1 because the second self-increment is on a temporary object.
- Also, for built-in types, expressions such as (i++) + + cannot be compiled. The operator overloads of the custom type should be consistent with the built-in type retention behavior .
The return type of a++ can certainly be compiled if it is changed to a non-const object, but we'd better not do that.
Why is the return type of ++a a reference?
The reason for doing this is to be consistent with the behavior of the built-in type. The predecessor + + returns the object itself that is always self-increasing. Therefore, the effect of + + (++a) is that a is increased two times.
The difference between formal parameters
The front + + has no formal parameters, and the next + + has an int parameter, but the parameter is not used. Strange, is there any special purpose?
In fact, there is no special purpose, just to circumvent the limitations of grammar .
Operator overloading functions for front + + and post + +, function prototypes must be different. Otherwise, the "overloaded function must have a different function prototype" syntax is violated.
Although the return type of the predecessor + + is different from the Post + +, the return type is not part of the function prototype. To circumvent the syntax restrictions, an int parameter was added to the Post + +.
The reason is so simple, there really is no other special purpose. In fact, adding a parameter to the front + + can also add a double parameter instead of an int parameter, or you can. It was only then that it was decided.
The difference between code implementations
The implementation of the front + + is relatively simple, since the increment, the *this return. It is important to note that you must return to *this.
The implementation of Post + + is a little more cumbersome. Since the object before the increment is returned, a copy of the object is first copied, then self-increment, and then the copy is returned.
In the age code, Post + + uses the front + + to achieve self-increment. This is done to avoid "self-increasing code" duplication.
In this example, the self-increment code is simple, which is a line of ++i, and there is no need to do so. But in other examples where the logic of self-amplification is complex, it is necessary to do so.
The difference between efficiency
If you do not need to return the value before the increment, both the predecessor + + and the Post + + are evaluated the same. However, we should still prioritize the use of Pre + +, especially for user-defined types of self-increment operations.
The predecessor + + is more efficient because the post + + generates a temporary object.
This can also be seen from the code implementation of Age's post + +.
Const operator+ + (int// post + + + { = * this; + + (* this); // using pre-built + + return tmp; }
Obviously, TMP is a temporary object that causes an additional overhead for the constructor and one destructor at a time. Although, the compiler can optimize these costs in some cases. However, we'd better not rely on compiler behavior.
Therefore, when the non-built-in type, try to use the front + +, because of high efficiency (rear self-increment, low efficiency)
Original link: http://blog.csdn.net/randyjiawenjie/article/details/6747720
(RPM) difference between front + + and post + +