AFAIK it is illegal to take the address of an rvalue because the address-of operator &
takes an lvalue and returns the address of the object's called on address.
Here is an example I've tried to understand but find it a bit confusing:
#include <deque>
#include <iostream>
int main() {
using std::cout;
using std::endl;
std::deque<int> di{ 1, 1, 2, 3, 5, 8, 13 };
std::deque<int>::iterator it = di.end() - 1;
cout << *it << endl;
cout << &it-- << endl; // is it UB?
cout << *it << endl;
cout << &it-- << endl;
cout << *it << endl;
cout << &it-- << endl;
cout << *it << endl << endl;
cout << &--it << endl; // ok
cout << *it << endl; // ok
cout << &--it << endl; // ok
cout << *it << endl; // ok
std::cout << std::endl << "done!" << std::endl;
}
In the lines where I've used the pre-decrement operator it is OK because this operator and
&
have the same precedence level and are evaluated from right-to-left (RL) thus--
evaluates first and it returns an lvalue (takes also lvalue). then&
is evaluated so&
on an lvalue is OK.The problem above in the post-decrement operator which takes an lvalue and returns an rvalue and has higher precedence over
&
. So in these expressions I am calling&
on rvalue which is normally not allowed. But why the code compile and gives different results (addresses)??When compiled on Wandbox with flag
-pedantic
it doesn't compile:prog.cc:25:17: error: taking address of rvalue [-fpermissive] 25 | cout << &offEnd-- << endl; // -- has higher precedence than & thus this expression decrements offEnd and returns a copy of original of offEnd then print the address of this original object (before decrementing it)
Also on MSVC++14 with
/Wall
.So is it undefined behavior in my code?
- so why C++ allowed calling address of operator
&
on rvalue while the standard disallows it? - Finally I want to know where theses different addresses come from in such expression:
std::cout << &it-- << std::endl;
? But the values of de-referencing are correct!