2014-06-12 4 views
16

Это неопределенное поведение:Порядок оценки параметров функции: это UB, если мы передаем ссылку?

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? Важно знать, потому что компилятор может свободно что-либо делать, если обнаруживает неопределенное поведение, даже если я знаю, что он всегда даст те же результаты.


Примечание: Я оставлю feedMeReference(ra = 3, a) так как некоторые ответы ссылаются ra, но следует иметь в виду, что проще эквивалентная проблема это, если мы называем feedMeReference(a = 3, a) (проще, потому что мы исключаем ra что только на пути нашего issue (второй параметр является ссылкой)).

+5

Как ваш компилятор это он, я предполагаю, что это будет выбор в пользу максимальной иррациональности. – Bathsheba

+0

@ Батшеба, да, я, как правило, персонифицирую компилятор. – bolov

+0

удалил локальную ссылку «ra», потому что я не думаю, что она имеет значение, и акцент делается на втором параметре, который является ref или нет. – bolov

ответ

12

Это интересный вопрос. В вашем первом случае существует неопределенное поведение , потому что объект изменен, а также доступ без промежуточной точки последовательности (на языке из C++ 03 --- C++ 11 используется другой язык, чтобы сказать, по существу, вещь). Во втором случае нет неопределенного поведения, , потому что инициализация ссылки с lvalue не имеет доступа к объекту , поэтому единственным доступом является ra = 3. (Вызов функции устанавливает точку последовательности, поэтому доступ в функции имеют точку последовательности между ними и ra = 3.)

+0

Можете ли вы сказать мне, если вместо '(ra = 3, a)' we have '(a = 3, a)' у нас есть то же самое? – bolov

+2

@bolov, да, это то же самое, так как 'ra' - просто псевдоним' a' – Erbureth

Смежные вопросы