Порядок оценки параметров функции: это UB, если мы передаем ссылку?
Это поведение undefined:
void feedMeValue(int x, int a) {
cout << x << " " << a << endl;
}
int main() {
int a = 2;
int &ra = a;
feedMeValue(ra = 3, a); // equivalent to: feedMeValue(a = 3, a) (see note bellow)
return 0;
}
потому что в зависимости от того, какой параметр оценивается, мы могли бы называть (3, 2)
или (3, 3)
.
Однако это:
void feedMeReference(int x, int const &ref) {
cout << x << " " << ref << endl;
}
int main() {
int a = 2;
int &ra = a;
feedMeReference(ra = 3, a); // equivalent to: feedMeReference(a = 3, a) (see note bellow)
return 0;
}
всегда будет выводить 3 3
, поскольку второй параметр является ссылкой, и все параметры были оценены до вызова функции, поэтому, даже если второй параметр оценивается до после ra = 3
, функция получила ссылку на a
который будет иметь значение 2
или 3
во время оценки, но всегда будет иметь значение 3
во время вызова функции.
Является ли второй пример UB? Важно знать, потому что компилятор может свободно что-либо делать, если обнаруживает поведение undefined, даже если я знаю, что он всегда даст те же результаты.
Примечание. Я оставлю feedMeReference(ra = 3, a)
в качестве ссылки на ответы ra
, но вы должны заметить, что проблема проще эквивалентна, если мы назовем feedMeReference(a = 3, a)
(проще, потому что мы исключаем ra
, который находится на пути нашей проблемы (второй параметр является ссылкой)).
Ответы
Ответ 1
Это интересный вопрос. В вашем первом случае
undefined, потому что объект изменен, а также
доступ без промежуточной точки последовательности (на языке
из С++ 03 --- С++ 11 использовал другой язык, чтобы сказать, по существу,
то же самое). Во втором случае поведение undefined отсутствует,
потому что инициализация ссылки с lvalue не имеет доступа
объект, поэтому единственный доступ - ra = 3
. (Вызов
функция устанавливает точку последовательности, поэтому доступ в
функция имеет точку последовательности между ними и ra = 3
.)