Increment operator inside array - c++

I have a C program which does queue operations using an array. In that program, they increment a variable inside array. I can't understand how that works. So, please explain these operations:
array[++i];
array[i++];

Please explain these operations.
array[++i]; - first increments i, then gives you element at the incremented index
equivalent to:
++i; // or i++
array[i];
array[i++]; - also first increments i, but postfix operator++ returns i's value before the incrementation
equivalent to:
array[i];
++i; // or i++
They increment a variable inside array.
No, they don't. You could say they increment i within the call to array subscript operator.

The ++i increments i before evaluating it.
The i++ inrements i after evaluating it.
If i=1 then array[++i] sets i=2 and then fetches array[2].
If i=1 then array[i++] fetches array[1] then sets i=2.
The post- and pre- operations happen after or before the expression they are involved in is evaluation.
I generally discourage the use of post and pre increment operators in expressions. They can lead to confusion at best and bugs at worst.
Consider what x = array[++i] + array[i--] ; should be. See how easy it is to confuse the programmer ( or the poor devil who has to fix your code ? :-) ).
Post and pre increment and decrement operations can also produce problems in macros, as you end up with the potential for an operation to be duplicated multiple times, especially with macros.
It is simpler and produces easier to maintain code to avoid post and pre increments in expressions, IMO.

So, you know i++ and ++i increment i with 1. Also, this instruction returns i, so you can put this somewhere in your code where you need the value of i.
The difference between the 2 is that i++ is post increment, and ++i is pre increment. What does this mean?
Well, let's say i is 6. When you do:
array[i++]
array[i]
You will actually be doing:
array[6]
array[7]
Because you use post increment: first return value, then increment i.
If you do:
array[++i]
array[i]
You'll basically be doing:
array[7]
array[7]
Because you use pre increment: first increment i, then return its value.
Now try to find what your code does ;-)
Hope this helps.

array[++i]; - increments the value of i and then uses the incremented value as an index into array
array[i++]; -indexes into the array and then increments the value of i

I know your question was in the context of a queue, but I'm going to use a stack for illustration.
Imagine an array-based stack:
T stack[N]; // for some type T
size_t sp = N; // stack pointer
In this example, the stack grows "downwards", where index N-1 is the bottom of the stack and index 0 is the top.
A push operation looks like the following:
stack[--sp] = val;
--sp evaluates to sp - 1, and as a side effect decrements the value in sp, so the above statement is equivalent to writing
stack[sp - 1] = val;
sp = sp - 1;
with the caveat that sp may be updated before the assignment is complete.
A pop operation looks like this:
val = stack[sp++];
sp++ evaluates the the current value of sp, and as a side effect increments the value in sp, so it's equivalent to writing
val = stack[sp];
sp = sp + 1;
with the same caveat as above.

Related

How is incrementing and dereferencing the iterator faster than incrementing a separate variable and indexing it into the array?

Why is the following:
for (auto & x : vec) { /* do stuff with x */ }
faster than
for (int i = 0; i < v.size(); ++i) { /* do stuff with v[i] */ }
As my title said, I was told that incrementing and dereferencing the iterator faster than incrementing a separate variable and indexing it into the array, but don't understand why?
What exactly is happening that makes it faster?
I tried to step through and see what was happening and this is what I came up with
// pseudo instructions
// iterator
increment iterator
e.g., if the object is 3 integers you would increment the iterator
by 12
dereference this iterator
// pseudo instructions
// array
increment array index
add 1 to index counter
multiply by size of object
e.g., if the object is 3 integers, you multiply by 12
dereference the array
Iterating through an array seems rather trivial. You are just doing the following:
[offset + index * size] ; An array takes this form in assembly
Which would look something like this if you have an array of integers
[rbp - 16 + rdi * 4] ; rbp - 16 is the offset
; rdi is the index
; 4 is the size of the integer
The array iteration seems rather trivial, so I don't understand how dereferencing an iterator is faster.
The only way it MAY be faster, at least in unoptimized code is because you call size() member function at beginning of every iteration and it's really depends on container and type of iterator it uses. Otherwise using iterators for array-like container is same as using pointer arithmetics and which order is faster depends on optimization. Also it would help if i would be of appropriate type size to not confuse compiler by different width of values.
Range-based for loop got more invalidation issues than index-based though if you're in process of modifying same container. Because it coded in this way:
The range-based for statement
for ( for-range-declaration : for-range-initializer ) statement
is equivalent to
{
auto &&__range = for-range-initializer ;
auto __begin = begin-expr ;
auto __end = end-expr ;
for ( ; __begin != __end; ++__begin ) {
for-range-declaration = *__begin;
statement
}
}
As you see, iterators for begin and end of range are evaluated before loop and any actions taken upon the range which invalidates them would invoke an UB.
If we speak of generic idea of container and not just std::vector, for some containers operator[] may be way more expensive than iterator increment. Only a few number of standard containers have constant cost of operator[] and in case of views\ranges its cost is generally larger, non-constant or non-linear. Cost of incrementing iterators tends to be constant or linear. Costs are usually declared or can be found out during performance tests.
So main issue is not performance but correctness of code, and use of range-based for loop suggests that range wasn't changed in it. It makes harder to cause such change deliberately because all that you have access to is a reference or a copy of an element. An attempt to do so would be obvious, it would be some usage of original range. It also saves from boilerplate code of begin-expr/end-expr.
In common for-loop calling size in i < v.size() may suggest that size() could change during execution. If it's true and happens in middle of loop's body, you may find out that index is out of bound from that point.
When reviewing code not knowing author of code, If I look for source of such change, every such loop is a suspect in detected bug or crash on out-of-bound access from the moment I saw its first line followed by some non-transparent code.
Is for (auto & x : vec) { /* do stuff with x */ } faster than for (int i = 0; i < v.size(); ++i) { /* do stuff with v[i] */ }?
When you talk about faster in absolutes you are basically always wrong. Every case is different. A simple change in the stack alignment can make as much as a 40% difference in the speed of your code, which is more than the difference between -O0 and -O2 in general. So simply adding a local variable to some function earlier in the call graph can completely reverse what is faster.
Always measure the performance of your code with real inputs!
That said, the for loop invokes v.size() in every iteration. The auto loop does not do that. The compiler may or may not be able to realize that the change of v never changes for the duration of the loop. If it doesn't that will cause slow downs.
But if it does both ways of writing the loop should turn into this (on x86_64):
size_t count = vec.end() - vec.begin();
T *it = vec.begin();
while (count-- > 0) {
/* do stuff with *it */
++it;
}
That's usually the form a well optimized loop takes. Or more specifically in asm a do{}while(--count != 0) with code outside the loop to not enter it if it should run zero iterations. Or do{}while(++ptr < endptr) to use it itself as the loop counter, avoiding having to actually calculate a count out of pointer-subtraction.
Your idea that array access should take the form [rbp - 16 + rdi * 4] is false. While that is perfectly reasonable to write by hand the resulting machine code is larger than using [rdi] and add rdi, 4 once per loop. This will save instruction cache, especially if the pointer is accessed multiple times, and end up being faster. The > 0 test is also simpler than < end when you deal with an index, so if the compiler uses a separate count register, it can do dec rcx / jnz .loop_top (1 uop on Intel) instead of inc / cmp / jne (needing a 2nd register for the limit, and is 2 uops on Intel and AMD, macro-fusing the cmp+jcc).
Overall if one of the two forms is faster than the other then it is either a failure to optimize (the same way) or that v.size() call being impossible to eliminate.

Using nested [ ] operations for std::vector

I am quite new to C++, and i have tried searching for an answer to this and running tests, but many times I'm having trouble figuring out what causes specific behaviors.
My question relates to using nested [ ] operators to access or modify elements in a loop - example:
//Declare
std::vector<int> a1 {10,20,30,40} ;
std::vector<int> a2 {2,3} ;
int S2 = a2.size() ;
//Loop
for(int i = 0 ; i < S2 ; i++){
a1[a2[i]] = a1[a2[i]] + 5000 ;
}
Is this considered ok? I'm asking not only in terms of common practice, but also in terms of efficiency and any other potential factor I need to consider.
Am I supposed to first store a[i] inside a temporary variable inside the loop and then use it to modify my element in vector a2?
I do know that its probably not the best structure and I should be using some other data structure to do this kind of thing, but I just want to understand if this is ok or if it might cause some undefined behavior.
I am developer for a finite element calculation software.
We use this technique in order to access the values inside an element. It helps us to save a lot of memory
BUT: Be aware that it spoils your cache locality. Don't use it in heavy loops, if you can avoid it.
If you need a range checks and performance is not important, you can consider using the at operator of the std::vector
for(const auto & index :a2) {
a1.at(index) += 5000;
}
The at function automatically checks whether n is within the bounds of valid elements in the vector, throwing an out_of_range exception if it is not (i.e., if n is greater than, or equal to, its size). This is in contrast with member operator[], that does not check against bounds.
Moreover, consider using a range based loop
//Loop
for(const auto & index :a2) {
a1[index] += 5000;
}
This is perfectly correct.
But in fact, you just want to iterate the elements of a standard container. C++ allows the range based for statement for that use case:
for (index: a2) {
a1[index] += 5000;
}
I find it more readable even if it is mainly a matter of taste...
Disclaimer: this code makes no control of the validity of the elements of a2 as index of a1.
Looks okay to me. There is no need to create an explicit copy of a2[i].
The only issue I see with something like this is that the argument inside [] should be of type std::size_t instead of int. These integer types encompass different ranges of values, and while std::size_t is an unsigned integer type, int is a signed integer. Beware of using negative indexes or indexes past the last element will likely result in undefined behavior due to out-of-bounds access. But if you can guarantee that the values in a2 are always valid indexes for a1, then these int values will implicitly be converted to std::size_t and things works properly (which seems to be the case in the code example in your question).
I also suggest to convert the loop variable i to std::size_t (and use ++i instead of i++ if you want to be perfect:).
In modern C++, you can also use a range-based for so you don't have use an explicit index variable for accessing a2 values at all:
for (auto indexFromA2 : a2)
a1[indexFromA2] += 5000;
This is less error-prone, because you have to write less logic for managing the element access (and don't have to spell out the types).
I would somehow ensure that the elements in a1 defined in a2 do really exist before trying to access them, otherwise you run out of bounds.
But in regards of nested [] this is fine and there's no need to create another copy of a2 to access a1. The compiler is just unwrapping your expression from inside out.
You can still simplify your code a bit
//Declare
std::vector<int> a1 {10,20,30,40} ;
std::vector<int> a2 {2,3} ;
//Loop
for(int i = 0 ; i < a2.size() ; i++){
if(a1.size()-1 < a2[i]){break;}
a1[a2[i]] += 5000 ;
}

c++ : unsequenced modification and access to "i"

My ideas were quite simple.
I wish to copy element by element from vector temp to vector data.
void copy(vector<int> &data, vector<int> &temp)
{
int i=0;
while (i<data.size()) {
data[i]=temp[i++];//unsequenced modification and access to "i"
cout<<i<<endl;
}
Outputs:
temp={1,2,3,4}
but data={1,1,2,3}
even if i's cout values are 1,2,3,4
wonder why.
Thanks for help in advance!
The line
data[i]=temp[i++];//unsequenced modification and access to "i"
has undefined behavior. The result of executing the line will be different depending on whether data[i] is evaluated first or temp[i++] is evaluated first.
Use
while (i<data.size()) {
data[i]=temp[i];
++i;
}
As an alternative, use the std::copy function.
void copy(vector<int> &data, vector<int> &temp)
{
std::copy(temp.begin(), temp.end(), data.begin());
}
One might wonder why the behavior in a case like this isn't defined to be equivalent to incrementing in a separate statement following the one in question. I imagine the reason is that processors have some ability to do post increment for you (see the lodsw family of instructions). When using those instructions, the post increment must occur at the time you fetch the data. So to guarantee the post increment followed all other uses of the incremented variable would require that that fetch be done last, or at least after all other uses of the rsi in that statement. The designers probably decided that was too constraining.
Why people says about undefined behavior?
data[i]=temp[i++];
In this case, first, we will take value from temp[I] (example: y), then "i" will be incremented by 1 (i++), and after that, value from temp[i] (y in our case) will be stored in data[i], where "i" is already incremented by 1.

How do I put two increment statements in a C++ 'for' loop?

I would like to increment two variables in a for-loop condition instead of one.
So something like:
for (int i = 0; i != 5; ++i and ++j)
do_something(i, j);
What is the syntax for this?
A common idiom is to use the comma operator which evaluates both operands, and returns the second operand. Thus:
for(int i = 0; i != 5; ++i,++j)
do_something(i,j);
But is it really a comma operator?
Now having wrote that, a commenter suggested it was actually some special syntactic sugar in the for statement, and not a comma operator at all. I checked that in GCC as follows:
int i=0;
int a=5;
int x=0;
for(i; i<5; x=i++,a++){
printf("i=%d a=%d x=%d\n",i,a,x);
}
I was expecting x to pick up the original value of a, so it should have displayed 5,6,7.. for x. What I got was this
i=0 a=5 x=0
i=1 a=6 x=0
i=2 a=7 x=1
i=3 a=8 x=2
i=4 a=9 x=3
However, if I bracketed the expression to force the parser into really seeing a comma operator, I get this
int main(){
int i=0;
int a=5;
int x=0;
for(i=0; i<5; x=(i++,a++)){
printf("i=%d a=%d x=%d\n",i,a,x);
}
}
i=0 a=5 x=0
i=1 a=6 x=5
i=2 a=7 x=6
i=3 a=8 x=7
i=4 a=9 x=8
Initially I thought that this showed it wasn't behaving as a comma operator at all, but as it turns out, this is simply a precedence issue - the comma operator has the lowest possible precedence, so the expression x=i++,a++ is effectively parsed as (x=i++),a++
Thanks for all the comments, it was an interesting learning experience, and I've been using C for many years!
Try this
for(int i = 0; i != 5; ++i, ++j)
do_something(i,j);
Try not to do it!
From http://www.research.att.com/~bs/JSF-AV-rules.pdf:
AV Rule 199
The increment expression in a for loop will perform no action other than to change a single
loop parameter to the next value for the loop.
Rationale: Readability.
for (int i = 0; i != 5; ++i, ++j)
do_something(i, j);
I came here to remind myself how to code a second index into the increment clause of a FOR loop, which I knew could be done mainly from observing it in a sample that I incorporated into another project, that written in C++.
Today, I am working in C#, but I felt sure that it would obey the same rules in this regard, since the FOR statement is one of the oldest control structures in all of programming. Thankfully, I had recently spent several days precisely documenting the behavior of a FOR loop in one of my older C programs, and I quickly realized that those studies held lessons that applied to today's C# problem, in particular to the behavior of the second index variable.
For the unwary, following is a summary of my observations. Everything I saw happening today, by carefully observing variables in the Locals window, confirmed my expectation that a C# FOR statement behaves exactly like a C or C++ FOR statement.
The first time a FOR loop executes, the increment clause (the 3rd of its three) is skipped. In Visual C and C++, the increment is generated as three machine instructions in the middle of the block that implements the loop, so that the initial pass runs the initialization code once only, then jumps over the increment block to execute the termination test. This implements the feature that a FOR loop executes zero or more times, depending on the state of its index and limit variables.
If the body of the loop executes, its last statement is a jump to the first of the three increment instructions that were skipped by the first iteration. After these execute, control falls naturally into the limit test code that implements the middle clause. The outcome of that test determines whether the body of the FOR loop executes, or whether control transfers to the next instruction past the jump at the bottom of its scope.
Since control transfers from the bottom of the FOR loop block to the increment block, the index variable is incremented before the test is executed. Not only does this behavior explain why you must code your limit clauses the way you learned, but it affects any secondary increment that you add, via the comma operator, because it becomes part of the third clause. Hence, it is not changed on the first iteration, but it is on the last iteration, which never executes the body.
If either of your index variables remains in scope when the loop ends, their value will be one higher than the threshold that stops the loop, in the case of the true index variable. Likewise, if, for example, the second variable is initialized to zero before the loop is entered, its value at the end will be the iteration count, assuming that it is an increment (++), not a decrement, and that nothing in the body of the loop changes its value.
I agree with squelart. Incrementing two variables is bug prone, especially if you only test for one of them.
This is the readable way to do this:
int j = 0;
for(int i = 0; i < 5; ++i) {
do_something(i, j);
++j;
}
For loops are meant for cases where your loop runs on one increasing/decreasing variable. For any other variable, change it in the loop.
If you need j to be tied to i, why not leave the original variable as is and add i?
for(int i = 0; i < 5; ++i) {
do_something(i,a+i);
}
If your logic is more complex (for example, you need to actually monitor more than one variable), I'd use a while loop.
int main(){
int i=0;
int a=0;
for(i;i<5;i++,a++){
printf("%d %d\n",a,i);
}
}
Use Maths. If the two operations mathematically depend on the loop iteration, why not do the math?
int i, j;//That have some meaningful values in them?
for( int counter = 0; counter < count_max; ++counter )
do_something (counter+i, counter+j);
Or, more specifically referring to the OP's example:
for(int i = 0; i != 5; ++i)
do_something(i, j+i);
Especially if you're passing into a function by value, then you should get something that does exactly what you want.

Incrementing in C++ - When to use x++ or ++x?

I'm currently learning C++ and I've learned about the incrementation a while ago.
I know that you can use "++x" to make the incrementation before and "x++" to do it after.
Still, I really don't know when to use either of the two... I've never really used "++x" and things always worked fine so far - so, when should I use it?
Example: In a for loop, when is it preferable to use "++x"?
Also, could someone explain exactly how the different incrementations (or decrementations) work? I would really appreciate it.
It's not a question of preference, but of logic.
x++ increments the value of variable x after processing the current statement.
++x increments the value of variable x before processing the current statement.
So just decide on the logic you write.
x += ++i will increment i and add i+1 to x.
x += i++ will add i to x, then increment i.
Scott Meyers tells you to prefer prefix except on those occasions where logic would dictate that postfix is appropriate.
"More Effective C++" item #6 - that's sufficient authority for me.
For those who don't own the book, here are the pertinent quotes. From page 32:
From your days as a C programmer, you may recall that the prefix form of the increment operator is sometimes called "increment and fetch", while the postfix form is often known as "fetch and increment." The two phrases are important to remember, because they all but act as formal specifications...
And on page 34:
If you're the kind who worries about efficiency, you probably broke into a sweat when you first saw the postfix increment function. That function has to create a temporary object for its return value and the implementation above also creates an explicit temporary object that has to be constructed and destructed. The prefix increment function has no such temporaries...
From cppreference when incrementing iterators:
You should prefer pre-increment
operator (++iter) to post-increment
operator (iter++) if you are not going
to use the old value. Post-increment
is generally implemented as follows:
Iter operator++(int) {
Iter tmp(*this); // store the old value in a temporary object
++*this; // call pre-increment
return tmp; // return the old value }
Obviously, it's less efficient than
pre-increment.
Pre-increment does not generate the temporary object. This can make a significant difference if your object is expensive to create.
I just want to notice that the geneated code is offen the same if you use pre/post incrementation where the semantic (of pre/post) doesn't matter.
example:
pre.cpp:
#include <iostream>
int main()
{
int i = 13;
i++;
for (; i < 42; i++)
{
std::cout << i << std::endl;
}
}
post.cpp:
#include <iostream>
int main()
{
int i = 13;
++i;
for (; i < 42; ++i)
{
std::cout << i << std::endl;
}
}
_
$> g++ -S pre.cpp
$> g++ -S post.cpp
$> diff pre.s post.s
1c1
< .file "pre.cpp"
---
> .file "post.cpp"
The most important thing to keep in mind, imo, is that x++ needs to return the value before the increment actually took place -- therefore, it has to make a temporary copy of the object (pre increment). This is less effecient than ++x, which is incremented in-place and returned.
Another thing worth mentioning, though, is that most compilers will be able to optimize such unnecessary things away when possible, for instance both options will lead to same code here:
for (int i(0);i<10;++i)
for (int i(0);i<10;i++)
I agree with #BeowulfOF, though for clarity I would always advocate splitting the statements so that the logic is absolutely clear, i.e.:
i++;
x += i;
or
x += i;
i++;
So my answer is if you write clear code then this should rarely matter (and if it matters then your code is probably not clear enough).
If count{5};
If you use ++count it will be process beforethe statement
total = --count +6;
Total will be equal to 10
If you use count++ it will be process after the statement
total = count-- +6;
Total will be equal to 11
Just wanted to re-emphasize that ++x is expected to be faster than x++, (especially if x is an object of some arbitrary type), so unless required for logical reasons, ++x should be used.
Postfix form of ++,-- operator follows the rule use-then-change ,
Prefix form (++x,--x) follows the rule change-then-use.
Example 1:
When multiple values are cascaded with << using cout then calculations(if any) take place from right-to-left but printing takes place from left-to-right e.g., (if val if initially 10)
cout<< ++val<<" "<< val++<<" "<< val;
will result into
12 10 10
Example 2:
In Turbo C++, if multiple occurrences of ++ or (in any form) are found in an expression, then firstly all prefix forms are computed then expression is evaluated and finally postfix forms are computed e.g.,
int a=10,b;
b=a++ + ++a + ++a + a;
cout<<b<<a<<endl;
It's output in Turbo C++ will be
48 13
Whereas it's output in modern day compiler will be (because they follow the rules strictly)
45 13
Note: Multiple use of increment/decrement operators on same variable
in one expression is not recommended. The handling/results of such
expressions vary from compiler to compiler.
You explained the difference correctly. It just depends on if you want x to increment before every run through a loop, or after that. It depends on your program logic, what is appropriate.
An important difference when dealing with STL-Iterators (which also implement these operators) is, that it++ creates a copy of the object the iterator points to, then increments, and then returns the copy. ++it on the other hand does the increment first and then returns a reference to the object the iterator now points to. This is mostly just relevant when every bit of performance counts or when you implement your own STL-iterator.
Edit: fixed the mixup of prefix and suffix notation
You asked for an example:
This (order is a std::vector) will crash for i == order.size()-1 on the order[i].size() access:
while(i++ < order.size() && order[i].size() > currLvl);
This will not crash at order[i].size(), as i will be incremented, checked and the loop will be exited:
while(++i < order.size() && order[i].size() > currLvl);
Understanding the language syntax is important when considering clarity of code. Consider copying a character string, for example with post-increment:
char a[256] = "Hello world!";
char b[256];
int i = 0;
do {
b[i] = a[i];
} while (a[i++]);
We want the loop to execute through encountering the zero character (which tests false) at the end of the string. That requires testing the value pre-increment and also incrementing the index. But not necessarily in that order - a way to code this with the pre-increment would be:
int i = -1;
do {
++i;
b[i] = a[i];
} while (a[i]);
It is a matter of taste which is clearer and if the machine has a handfull of registers both should have identical execution time, even if a[i] is a function that is expensive or has side-effects. A significant difference might be the exit value of the index.