以此示例代码:
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
,但情况正好相反。
这些场景的规则是否具体定义以及如何定义?此外,编译器是否区分赋值和其他运算符,如果在不同于初始化的上下文中使用=
运算符,那么该怎么可能?也许链分配与其他链接的处理方式不同?
答案 0 :(得分:24)
完整的表达
foo1() = foo2() = foo3() = 7
可以使用以下树抽象:
=
/ \
foo1() =
/ \
foo2() =
/ \
foo3() 7
可以按任何顺序评估该树的叶子。您的编译器可以自由选择。仅用于调用赋值运算符时,必须首先计算挂在它们上的表达式。在您的情况下,根据foo1()
,foo2()
和foo3()
的顺序评估树叶。
=
的右到左关联只能在树的形状中看到,而不是按照评估的顺序。
std::cout << foo1() << foo2() << foo3()
看起来像
<<
/ \
<< foo3()
/ \
<< foo2()
/ \
std::cout foo1()
同样可以按任何顺序评估foo
函数,但operator<<()
的评估顺序是明确定义的。有一个有趣的post about sequence points可以很好地描述这些主题。
答案 1 :(得分:15)
操作员关联性(即从右到左)与评估订单无关。 * 操作数的评估顺序未指定。
<小时/> *除少数情况外,即
&&
,||
和,
。
答案 2 :(得分:2)
如何评估子表达式的顺序与其结果的应用方式不同!
foo1()可以提前调用,只有在其他人也完成之前不能应用赋值本身。