The topic about evaluation order says that following code leads to undefined behavior until C++17:
a[i] = i++;
This happens due to unspecified order while evaluating left and right parts of the assignment expression.
C++14 standard 1.9/15 says:
If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a value computation using the value of the same scalar object, and they are not potentially concurrent (1.10), the behavior is undefined.
But what if we use std::vector
and its iterator
object instead of scalar object i
?
std::vector<int> v = {1, 2};
auto it = v.begin();
*it = *it++; // UB?
Is there undefined behaviour (until c++17) or not?
In C/C++ bitwise shifting a value by a number of bits which is either a negative number or is greater than or equal to the total number of bits in this value results in undefined behavior.
Unspecified behavior is different from undefined behavior. The latter is typically a result of an erroneous program construct or data, and no requirements are placed on the translation or execution of such constructs.
In situations when an iterator is a class, the behavior is well defined in all versions of the standard, assuming that it++
points to a valid location inside its container (which in your example it does).
C++ translates *it++
to this sequence of two function calls:
it.operator++(0).operator*();
Function calls introduce sequencing, so all side effects of the actual ++
invoked inside operator++
on the primitive used as an iterator's implementation (probably, a raw pointer) must complete before the function exit.
However, iterators are not required to be classes: they could be pointers, too:
struct foo {
typedef int* iterator;
iterator begin() { return data; }
private:
int data[10];
};
The code looks the same, and it continues to compile, but now the behavior is undefined:
foo f;
auto it = f.begin();
*it = *it++; // <<== This is UB
You can guard against this by invoking ++
as a member function:
std::vector<int> v = {1, 2};
auto it = v.begin();
*it = *it.operator++(0);
When the iterator is actually a pointer, this code will fail to compile, rather than causing undefined behavior.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With