Вычисляется ли выражение присваивания С++ 11 справа налево?

Порядок вычисления выражения всегда был источником неопределенного поведения в C++. В стандарте С++ 11 наконец указано, каким должен быть порядок оценки?

Теперь мы знаем значения var1 и var2 следующего выражения:

int var1 =10, var2=20;
var1 = var2 = 30;

Это будет var1=30 and var2=30 или var1=20 and var2=30?


person Dariusz    schedule 25.10.2013    source источник
comment
@Dariusz: код также не имеет ничего общего с реальной проблемой.   -  person Kerrek SB    schedule 25.10.2013
comment
@KerrekSB это МОЙ вопрос, и я знаю, что хотел спросить. Хотя у меня могут возникнуть проблемы с выражением того, что я имею в виду, код остается в силе. Ваш ответ не имеет ничего общего с тем, что я собирался опубликовать.   -  person Dariusz    schedule 25.10.2013
comment
@Dariusz: Чепуха. Вы спрашиваете о порядке вычисления выражений, и код, который вы разместили, не имеет к этому никакого отношения. Опубликованное вами выражение — a = b, где b — это var2 = 30 и имеет значение 30, а a — это var1 и является lvalue. Порядок не имеет ничего общего с результатом вычисления этого выражения.   -  person Kerrek SB    schedule 25.10.2013
comment
@Dariusz: Чтобы дать другую точку зрения: кажется, вы путаете вопросы грамматики (ассоциативность операторов, которая определяет как анализируется исходный код) и абстрактные правила оценки выражений. Здесь нет ничего двусмысленного.   -  person Kerrek SB    schedule 25.10.2013
comment
Вопрос изначально некорректен. Мне не удалось правильно сформулировать то, что я хотел спросить, я хотел бы создать вопрос с нуля и на этот раз правильно и получить реальные ответы на вопрос, который не редактировался 10 раз. Пожалуйста, удалите этот.   -  person Dariusz    schedule 25.10.2013
comment
@KerrekSB Мне наконец-то удалось спросить, что я хотел спросить, см. заголовок stackoverflow.com/questions/19585808/   -  person Dariusz    schedule 25.10.2013
comment
@Dariusz: Спасибо. Я также добавил немного текста, относящегося к вашему коду.   -  person Kerrek SB    schedule 25.10.2013


Ответы (3)


var1 = var2 = 30;

Оба должны быть 30, и это указано в стандарте. Вещь, которая не указана, заключается в том, что если присваивание операндов является сложным выражением, которое должно быть оценено перед присвоением, какова последовательность их оценки?

(expr1) = (expr2) = x;
   1         2

or

(expr1) = (expr2) = x;
   2         1
person masoud    schedule 25.10.2013
comment
Всегда ли это было? Каков порядок вычисления этих сложных выражений сейчас и каким он был? - person Dariusz; 25.10.2013
comment
Мы не знаем порядок, и он не указан стандартом. - person masoud; 25.10.2013

Нет, новый стандарт не определяет последовательность или порядка вычислений всех подвыражений.

Выражение a + b + c грамматически сгруппировано как (a + b) + c, но три подвыражения a, b и c могут оцениваться в любом порядке, и оценки не упорядочены друг относительно друга.

Чтобы сделать это более конкретным, рассмотрим:

int main()
{
    return printf("Hello") + printf("World") + printf("\n");
}

Что касается вашего кода: там нет никакой двусмысленности. Это одно выражение, выражение присваивания формы a = b, где a — lvalue var1, а b — подвыражение var2 = 30. Тот факт, что вам интересно, заканчивается ли var1 20 или 30, наводит меня на мысль, что вы не уверены в ассоциативности оператора (для =). Это, однако, никогда не было двусмысленным и прекрасно определено во всех языковых вариантах, которые я могу придумать. Оператор присваивания связан справа, что приводит к подвыражениям a и b, которые я описал. Этот (чрезвычайно фундаментальный) аспект языка не претерпел изменений в C++11.

Если вы действительно хотите объединить две проблемы, вам следует рассмотреть следующее выражение:

var1 = 10;
(var1 = 20) = (var2 = var1);

Теперь конечное выражение также равно a = b, но и a, и b являются нетривиальными подвыражениями, оценка которых не упорядочена.

person Kerrek SB    schedule 25.10.2013
comment
Вопрос касается = (справа налево), а не + (слева направо). См. Приоритет оператора. - person Daniel Frey; 25.10.2013
comment
@jrok ОП, похоже, что-то смутил, поэтому ответ должен попытаться решить эту проблему и помочь, а не усугублять путаницу. Я не отрицал этот ответ, поскольку он, как вы сказали, касается той же основной точки зрения, но это все же не очень хороший ответ - ваш лучше, поэтому я проголосовал за ваш. - person Daniel Frey; 25.10.2013
comment
@DanielFrey: это ассоциативность, а не приоритет. Я добавил абзац, посвященный коду OP. - person Kerrek SB; 25.10.2013
comment
+1 Теперь есть что-то полезное, и да, вы правы, это ассоциативность, а не приоритет. - person Daniel Frey; 25.10.2013

Оператор присваивания (=) и составные операторы присваивания группируются справа налево.

Это ничего не говорит нам о порядке оценки. Это просто означает, что a = b = c анализируется как a = (b = c), а не (a = b) = c.

1.9/15 по-прежнему применяется:

Если не указано иное, вычисления операндов отдельных операторов и подвыражений отдельных выражений не упорядочены.

Правила упорядочивания вводят только частичный порядок. В таком выражении:

(x+42) = (y+42)

гарантируется, что оба подвыражения (x+42) и (y+42) будут выполнены до присваивания результату (x+42), но сами два подвыражения не упорядочены. Любой из них может выполняться раньше другого, и их можно даже чередовать, и порядок не обязательно должен быть постоянным во время выполнения программы.

person jrok    schedule 25.10.2013