我很难理解下面代码中的调用顺序。 我期待看到下面的输出
A1B2
虽然我可以看到我得到的输出是
BA12
我认为通话std::cout<< b->fooA() << b->fooB() << std::endl
等同于通话
std::cout.operator<<( b->fooA() ).operator<< ( b->fooB() )
但我可以看到情况并非如此。你能帮助我更好地理解它是如何运作的以及与全球operator<<
的关系吗?这最后一次是按照这个顺序调用的吗?
此致
AFAG
#include <iostream>
struct cbase{
int fooA(){
std::cout<<"A";
return 1;
}
int fooB(){
std::cout <<"B";
return 2;
}
};
void printcbase(cbase* b ){
std::cout << b->fooA() << b->fooB() << std::endl;
}
int main(){
cbase b;
printcbase( &b );
}
答案 0 :(得分:9)
编译器可以将函数printcbase()
评估为:
void printcbase(cbase* b ){
int a = b->FooA(); // line 1
int b = b->FooB(); // line 2
std::cout << a; // line 3
std::cout << b; // line 4
stc::cout << std::endl;
}
或标记为1 - 4的许多线条的一些。只保证第1行在第3行之前完成,第2行在第4行之前完成(当然第4行在第4行之前)。标准没有说更多,实际上你可以期望使用不同的C ++编译器得到不同的结果。
答案 1 :(得分:5)
<<
的执行顺序已明确定义,但子表达式的评估顺序未在C ++中定义。 This article and the C code example说明了您提到的问题。
BA12
和AB12
都是正确的。在以下代码中:
std::cout<< b->fooA() << b->fooB()
1
将出现在2
之前,但A
可能出现在B
之前或之后,因为编译器未承诺是否会评估{首先{1}}或fooA
。
答案 2 :(得分:2)
移位运算符是左关联的; a << b << c
读为(a << b) << c
,这意味着如果a
属于具有成员用户定义的operator<<
的类型(并返回该类型),那么表达式将显示为{{1} }}。如果使用免费的a.operator<<(b).operator<<(c)
,则会将其显示为operator<<
。
因此,在评估operator<<(operator<<(a, b), c)
之前对a << b
的评估进行了排序,但(a << b) << c
和b
的评估之间没有排序依赖关系:
c
如果我们对副作用进行编号,那么副作用可以按以下任何一种顺序排列:
a << b << c[1]
| |
a << b[2] |
| | c[5]
a[3] b[4]