2

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!
L. F.
  • 19,445
  • 8
  • 48
  • 82
Itachi Uchiwa
  • 3,044
  • 12
  • 26
  • 4
    *"why C++ allowed calling address of operator & on r-value while the standard disallows it?"* - I don't understand this - there is no distinction between C++ and the standard, it's simply not allowed. Did you mean to ask why the compiler allows this? – UnholySheep Sep 21 '19 at 11:50
  • @StoryTeller: Yes I meant it. – Itachi Uchiwa Sep 21 '19 at 11:51
  • @UnholySheep; Yes I meant the compiler. So the different addresses come from U.B? – Itachi Uchiwa Sep 21 '19 at 11:52
  • 1
    This is not undefined behavior: the defined behavior is a compiler error since this is not allowed in standard. You might need to dig into the generated assembly to see what your compiler is doing in this case – arithma Sep 21 '19 at 11:59
  • 4
    The correct term is "ill-formed". – HolyBlackCat Sep 21 '19 at 12:00
  • 1
    @arithma: Did you mean 'the Undefined Behavior is compiler error.."? – Itachi Uchiwa Sep 21 '19 at 12:08
  • @arithma It appears that the value category of `r--` is unspecified, where `r` is an iterator, per [Table 98](https://timsong-cpp.github.io/cppwp/n4659/bidirectional.iterators#tab:iterator.bidirectional.requirements). – L. F. Sep 21 '19 at 13:51
  • [Somewhat related](https://stackoverflow.com/questions/57842756/why-should-i-always-enable-compiler-warnings). Some compilers have extensions turned on by default, and without warnings on you never know. – n. m. could be an AI Sep 21 '19 at 15:24

0 Answers0