C++中operator<<调用顺序问题

本文探讨了C++中使用流操作符<<时遇到的一个奇怪现象:在不同的编译器下,即使关闭了优化选项,操作符的执行顺序也不一致,导致运行结果不同。作者通过测试发现,此行为与C++标准不符,并给出了相应的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天发现一个奇怪的问题,有一个函数,该函数会记录原来的状态,调用一次以后,下次调用就会使用原来的结果,从而提高性能,假如函数是这样的
int GetValue(bool update=false);
如果update=true则更新其值,否则不更新.在测试时我这样输出其值:

cout<

期望两个值是相等的,可是输出结果却不相等,单步跟踪发现,该句先调用的面的函数GetValue(),而后调用前面的GetValue(true),前都用的是旧值,而后者用的是新值,所以其值不同,感觉很奇怪。

其实应该是cout<cout.operator<<(GetValue(true))
该表达式返回一个cout的引用,然后调用cout.operator<<(GetValue())所以,其显示的调用应该是
(cout.operator<<(GetValue(true))).operator<<(GetValue())
然而两次的运行结果却不一样,在VC9和Cygwin中的gcc 3.3.4都试的,结果一致。

然而,我又试了一下operator>>此时个编译器执行顺序即不一致了。

下面是测试程序:

#include
using namespace std;

int GetValue(bool update=false)
{
static int val=0;
if(update)
val += 10;
return val;
}

int main(int argc, char* argv[])
{
char str[5];
int i=0;
str[4]=0;

cout<<"Implicit call:/n";
cout<<"GetValue(true)="< <<"; GetValue(false)="<

cout<<"Explicit call:/n";
(cout.operator<<(GetValue(true))).operator<<(GetValue())<

cout<<"Implicit int:/n";
cout<

i = 0;
cout<<"Please input 4 letters"< cin>>str[i++]>>str[i++]>>str[i++]>>str[i++];
cout<}

VC9编译后的执行结果:

Implicit call:
GetValue(true)=10; GetValue(false)=0
Explicit call:
2010
Implicit int:
543210
Please input 4 letters
a b c d e // 输入
dcba

Cygwin中gcc 3.3.4编译后的执行结果:

Implicit call:
GetValue(true)=10; GetValue(false)=0
Explicit call:
2010
Implicit int:
012345
Please input 4 letters
a b c d // 输入
abcd

而在C++的标准1998,2003版中的5.8 Shift operators也都明确说明了<< 和 >>是The shift operators << and >> group left-to-right. 而且我把优化选项已经关掉了,跟标准仍然不一致。显然这些编译器都没有按标准做。这编译器搞得“我很郁闷,很费解啊”!虽然operator<<的执行顺序两个编译器是一致的,但其它的编译器会不是又不一样呢?还没试呢,有时间再试试吧,即便是一致又有什么用呢?谁在写程序的时候倒着写啊?

结论:在operator<<和operator>>的表达式中要使用固定值,千万不要编写由于表达式中的子表达式执行顺序不一样,而可能造成运行结果不一样的情况,最保险的是根本就不要在这两个操作符构成的表达式中进行任何运算,如果想要使用运算,这两个表达式在每句中只出现一次,然后安排好句子的顺序,严格控制程序的执行结果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值