AFAIK, запрещено принимать адрес значения r, потому что оператор адреса &
принимает значение l и возвращает адрес вызываемого объекта по адресу.
Вот примерпопытался понять, но нашел это немного запутанным:
#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;
}
В строках, где я использовал оператор предварительного уменьшения, все в порядке, потому что этот оператор и &
имеюттот же уровень приоритета и оцениваются справа налево (RL), поэтому --
вычисляется первым и возвращает lvalue (принимает также lvalue).тогда &
вычисляется так, что &
для lvalue в порядке.
Проблема выше в операторе пост-декремента, который принимает lvalue и возвращает значение r и имеет более высокий приоритет над&
.Поэтому в этих выражениях я звоню &
на значение rvalue, которое обычно не допускается.Но почему код компилируется и дает разные результаты (адреса) ??
При компиляции в Wandbox с флагом -pedantic
он не компилируется:
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)
Также на MSVC ++ 14 с /Wall
.
Так что же это неопределенное поведение в моем коде?
- , так почему C ++ допускает вызывающий адрес оператора
&
на rvalue, в то время как стандарт запрещает это? - Наконец, я хочу знать, откуда поступают разные адреса в таком выражении:
std::cout << &it-- << std::endl;
?Но значения разыменования верны!