Возьмите этот пример кода:
int a = 10;
int b = 20;
int c = 30;
int & foo1() {
qDebug() << "foo1" << endl;
return a;
}
int & foo2() {
qDebug() << "foo2" << endl;
return b;
}
int & foo3() {
qDebug() << "foo3" << endl;
return c;
}
int main(void)
{
foo1() = foo2() = foo3() = 7;
}
Поскольку назначение идет справа налево, я ожидал увидеть foo3
первый и foo1
последний, но это наоборот.
Определены ли правила для таких сценариев и как? Кроме того, различает ли компилятор между присваиванием и другими операторами и как это возможно, если вы используете =
оператор в другом контексте, чем инициализация? Может быть, цепное присвоение трактуется иначе, чем другие цепочки?
Полное выражение
foo1() = foo2() = foo3() = 7
можно абстрагироваться с помощью следующего дерева:
=
/ \
foo1() =
/ \
foo2() =
/ \
foo3() 7
Листья этого дерева могут быть оценены в любом порядке. Ваш компилятор свободен в выборе. Только для вызова оператора присваивания выражения, висящие на них, должны оцениваться в первую очередь. В вашем случае листья оцениваются в порядке foo1()
, foo2()
а потом foo3()
,
Право на лево ассоциативность =
видно только в форме дерева, но не в порядке оценки. Дерево для
std::cout << foo1() << foo2() << foo3()
похоже
<<
/ \
<< foo3()
/ \
<< foo2()
/ \
std::cout foo1()
Опять foo
Функции могут быть оценены в любом порядке, но порядок оценки operator<<()
четко определен. Есть интересный пост о последовательности точек который описывает темы очень хорошо.
Ассоциативность оператора (то есть справа налево) не связана с порядок оценки.* Порядок оценки операндов не указан.
* За исключением нескольких случаев, а именно &&
, ||
а также ,
,
Порядок вычисления подвыражений не совпадает с тем, как применяется их результат!
Функция foo1 () может быть вызвана раньше, просто само назначение не должно применяться до того, как будут выполнены другие.