It is actually incremented first. However, note that the postfix version of ++ is used, which means that while s itself is incremented, the return value of the operator is the old value of s.
That is,
Code:
char *s = "Hello";
// *s == 'H'
char *t = s++;
// *t == 'H', *s == 'e'
*t = 'h'
// now t points to "hello". Well, it doesn't, since modifying a string literal will probably crash the program, but it would if the Hello array had been in modifiable memory to begin with.
This behavior is the reason why prefix increment, ++s, should be preferred unless you have a specific need for the postfix version. It's not only less confusing, it can in some cases be more efficient.
It is actually incremented first. However, note that the postfix version of ++ is used, which means that while s itself is incremented, the return value of the operator is the old value of s.
That is,
Code:
char *s = "Hello";
// *s == 'H'
char *t = s++;
// *t == 'H', *s == 'e'
*t = 'h'
// now t points to "hello". Well, it doesn't, since modifying a string literal will probably crash the program, but it would if the Hello array had been in modifiable memory to begin with.
This behavior is the reason why prefix increment, ++s, should be preferred unless you have a specific need for the postfix version. It's not only less confusing, it can in some cases be more efficient.
This behavior is the reason why prefix increment, ++s, should be preferred unless you have a specific need for the postfix version. It's not only less confusing, it can in some cases be more efficient.
Ok, now that we have a thread about that specific topic, I can ask this...
From plain old C I'm used to prefer the post-increment version unless it is specifically required otherwise, simply because it looks more familiar to me.
Am I right to assume that it wouldn't make a difference in terms of efficiency in C++ as long as it's about POD types?
It looks reasonable to me that I get a performance penalty if I use post-increment on non-POD types and I somehow process the result of that operation, because it is likely to require creation of a temporary object. But does it really make any difference if I don't use the result of the increment operation in further processing?
Ok, now that we have a thread about that specific topic, I can ask this...
From plain old C I'm used to prefer the post-increment version unless it is specifically required otherwise, simply because it looks more familiar to me.
Am I right to assume that it wouldn't make a difference in terms of efficiency in C++ as long as it's about POD types?
It looks reasonable to me that I get a performance penalty if I use post-increment on non-POD types and I somehow process the result of that operation, because it is likely to require creation of a temporary object. But does it really make any difference if I don't use the result of the increment operation in further processing?
In a single sentence, "postfix is never faster, and sometimes slower".
Under these conditions, there really is no reason to use postfix unless you need to.
As for your question of taste ("prefering postfix over prefix"), if you start getting experience in C++, or work with people who have a C++ back ground, you will notice that prefix is the preferred way, and postfix will start looking weird.
PS: The compiler may or may not optimize away and performance penalty, but why take the chance?
Is your question related to IO?
Read this C++ FAQ LITE article at parashift by Marshall Cline. In particular points 1-6.
It will explain how to correctly deal with IO, how to validate input, and why you shouldn't count on "while(!in.eof())". And it always makes for excellent reading.
Ok, now that we have a thread about that specific topic, I can ask this...
From plain old C I'm used to prefer the post-increment version unless it is specifically required otherwise, simply because it looks more familiar to me.
Am I right to assume that it wouldn't make a difference in terms of efficiency in C++ as long as it's about POD types?
It looks reasonable to me that I get a performance penalty if I use post-increment on non-POD types and I somehow process the result of that operation, because it is likely to require creation of a temporary object. But does it really make any difference if I don't use the result of the increment operation in further processing?
The main argument for me to not using post-increment on class types isn't the possible lack of efficiency but that the behavior is different to that on POD types. Look at the following code (which was a C sample code in Stroustrup's Annotated C++ Reference)
Code:
while (*p++ = *q++);
When p and q are char arrays the above is a perfect strcpy. When p and q are class types there is no way to let the post-increment on the right-hand happen after the assignment.
If you then see that increment operation on class types mainly is done for containers and their iterators you probably will decide for prefix increment same as me and I promise that it will look 'more familiar' to you within a very short period ;-)
When p and q are class types there is no way to let the post-increment on the right-hand happen after the assignment.
Sorry, but I do not quite understand the problem that you are presenting. Now, order of evaluation is implementation defined, but here it seems quite clear that the dereference of q must happen before its post-increment. Therefore, how does it matter if the assignment happens before or after the post-increment? With the normally expected semantics, the net effect should be the same, i.e., similiar to "a perfect strcpy".
C + C++ Compiler: MinGW port of GCC
Build + Version Control System: SCons + Bazaar
Sorry, but I do not quite understand the problem that you are presenting. Now, order of evaluation is implementation defined, but here it seems quite clear that the dereference of q must happen before its post-increment. Therefore, how does it matter if the assignment happens before or after the post-increment? With the normally expected semantics, the net effect should be the same, i.e., similiar to "a perfect strcpy".
There is no way to happen the assigmnent *p = *q prior to the post-increment operation of q++.
Regards, Alex
Maybe you are confusing evaluation order?
Regardless of type, when you write:
Code:
*p++ = *q++
Both p++ and q++ are evaluated first (but in undefined relative order).
Once this is done, operator= is called on the return values of p++ and q++, ie, the old values of p and q. (making it look like the assignment took place before increment)
There is no special magic or rules that applies only to PODs that do the assignments first, and then increments the values of p or q.
...
Either that, or I seem to not understand what you are saying. Your example (rewritten since incomplete) seems to work correctly:
Code:
#include <iostream>
#include <string>
int main()
{
char pArray[20] = { '\0' };
char* p = pArray;
std::string helloStr = "Hello";
//force the null terminator into string //Undefined behavior, but defined in practice
helloStr.c_str();
std::string::iterator q = helloStr.begin();
while (*p++ = *q++); //note that this reads string.end(), but should point '\0'. May crash in ranged debug
std::cout << pArray << std::endl;
}
Code:
output: Hello
Was this your full example?
Regards,
Is your question related to IO?
Read this C++ FAQ LITE article at parashift by Marshall Cline. In particular points 1-6.
It will explain how to correctly deal with IO, how to validate input, and why you shouldn't count on "while(!in.eof())". And it always makes for excellent reading.
Both p++ and q++ are evaluated first (but in undefined relative order).
Once this is done, operator= is called on the return values of p++ and q++, ie, the old values of p and q. (making it look like the assignment took place before increment)
There is no special magic or rules that applies only to PODs that do the assignments first, and then increments the values of p or q.
...
Either that, or I seem to not understand what you are saying. Your example (rewritten since incomplete) seems to work correctly:
Code:
#include <iostream>
#include <string>
int main()
{
char pArray[20] = { '\0' };
char* p = pArray;
std::string helloStr = "Hello";
//force the null terminator into string //Undefined behavior, but defined in practice
helloStr.c_str();
std::string::iterator q = helloStr.begin();
while (*p++ = *q++); //note that this reads string.end(), but should point '\0'. May crash in ranged debug
std::cout << pArray << std::endl;
}
Sorry, but I do not quite understand the problem that you are presenting. Now, order of evaluation is implementation defined, but here it seems quite clear that the dereference of q must happen before its post-increment. Therefore, how does it matter if the assignment happens before or after the post-increment? With the normally expected semantics, the net effect should be the same, i.e., similiar to "a perfect strcpy".
I'm being pedantic, but since you rarely make a mistake, I thought I'd chip in here... the part in bold is not correct. The precedence of the post increment and post decrement operators is higher than the precedence of the dereference operator. Therefore for an ISO Standard compliant compiler the post increment must happen before the dereference.
itsmeandnobodyelse: please provide the smallest and simplest compilable program that demonstrates what you claim.
EDIT:
This program appears to contradict your claims:
Code:
#include <iostream>
#include <deque>
class X
{
public:
explicit X(int n) : n(n) {}
// Sorry, I'm too lazy to use safe bool idiom,
// and explicit conversion functions might not yet be available to you.
operator bool() const
{
return n != 0;
}
int get() const
{
return n;
}
private:
int n;
};
int main()
{
using namespace std;
deque<X> one;
for (int i = 1; i <= 10; ++i)
{
one.push_back(X(i));
}
one.push_back(X(0));
deque<X> two(one.size(), X(-1));
deque<X>::iterator p = two.begin();
deque<X>::iterator q = one.begin();
while (*p++ = *q++);
for (deque<X>::size_type i = 0, size = two.size(); i < size; ++i)
{
cout << two[i].get() << endl;
}
}
The output I get is:
Code:
1
2
3
4
5
6
7
8
9
10
0
Last edited by laserlight; August 3rd, 2010 at 04:11 AM.
C + C++ Compiler: MinGW port of GCC
Build + Version Control System: SCons + Bazaar
Bookmarks