通过一道面试题来看 C++ 语言中的表达式求值


题目一:
int  a = 10 ,b = 6 ;
cout
<< a + b << "   " << a ++<< "   " << b ++

请说出上述语句的执行结果。
很多人看过这段代码后估计都会直接就写上了 16 10 6 这样的结果吧,但上机实验的输出结果是: 18 10 6
为什么会出现这样的结果,下面是我的分析过程,如果有不对的地方请大家指正。
为了跟踪代码的执行步骤,我设计了一个类X,这个类是对int的模拟,行为方面与int基本一致,除了会打印出一些帮助我们理解的信息,代码如下:

class  X
{
public :
    X(){cout
<< " default construct " << endl;}
    X(
int  a):i(a){ cout << " construct  " << i << endl;}
    
~ X(){ cout << " desconstruct  " << i << endl;}
    X(
const  X &  x):i(x.i)
    {
        cout
<< " copy construct  " << i << endl;
    }
    X
&   operator ++ ()
    {
        cout
<< " operator ++(pre)  " << i << endl;
        
++ i;
        
return   * this ;
    }
    
const  X  operator ++ ( int )
    {
        cout
<< " operator ++(post)  " << i << endl;
        X x(
* this );
        
++ i;
        
return  x;
    }
    X
&   operator = ( int  m)
    {
        cout
<< " operator =(int) " << endl;
        i 
=  m;
        
return   * this ;
    }
    X
&   operator = ( const  X &  x)
    {
        cout
<< " operator =(X) " << endl;
        i
= x.i;
        
return   * this ;
    }
    
/
    friend ostream &   operator << (ostream &  os, const  X &  x)
    {
        os
<< x.i;
        
return  os;
    }
    friend X 
operator + ( const  X &  a, const  X &  b)
    {
        cout
<< " operator + " << endl;
        return  X(a.i+b.i);
    }
    
//
public :
    
int  i;
};

然后执行以下代码:

    X a( 10 ),b( 6 );
    cout
<< " sum: "   << a + b << "  a: " << a ++<< "  b: " << b ++<< endl;

使用GCC4。5编译后,代码的执行结果如下:

construct 10
construct 6
operator ++(post) 6
copy construct 6
operator ++(post) 10
copy construct 10
operator +
construct 18
sum:18 a:10 b:6
desconstruct 18
desconstruct 10
desconstruct 6
desconstruct 7
desconstruct 11
我们来简单分析下这个执行过程:

construct 10
construct 6  //这两行输出对应于 X a(10),b(6); 

operator ++(post) 6
copy construct 6 //表明首先执行了  cout<<"sum:" <<a+b<<" a:"<<a++<<" b:"<<b++<<endl;这句中的 b++这个表达式,
                              b++这个表达式返回了一个值为6的临时对象,而b本身则变成了7。
operator ++(post) 10 
copy construct 10  //这句的分析同上

operator +
construct 18 //对应于表达式 a+b ,可以看到,此时的a和b已经变成了11和7。表达式返回了一个值为18的临时对象。

sum:18 a:10 b:6 //输出的结果,从结果可以看出,实际上打印出的值分别为 a+b,a++和b++三个表达式所返回的临时变量。

desconstruct 18 //a+b 表达式返回的临时变量的析构
desconstruct 10 //a++ 表达式返回的临时变量的析构
desconstruct 6 //b++表达式返回的临时变量的析构
desconstruct 7 //变量a 的析构

desconstruct 11  //变量b的析构

真相大白了。为什么编译器会这样来编译这个表达式呢?

其实<<在同一语句中连续使用,其实本质上是函数的复合调用:
cout<<a+b<<" "<<a++<<" "<<b++; 
本质上是
operator<<(operator<<(operator<<(cout,a+b),a++),b++)
由于c++函数的参数的求值顺序是从右至左的(c++标准虽未规定,但是基本所有的编译器是这么干的),所以参数的计算次序是:
b++ //7
a++ //11
a+b //18
cout<<18
cout<<10 //因为10已经先入栈了
cout<<6//同上

上述实验的环境均为GCC4。5  据同学说VS2010执行的结果在DEBUG下和RELEASE下居然分别为:16 10 6 和18 10 6,不过我没有去验证过,有兴趣的同学可以去验证并分析一下。

附上一篇专门讲解C/C++表达式求值的文章。http://blog.csdn.net/luciferisnotsatan/article/details/6456696


转载于:https://my.oschina.net/u/90679/blog/109042

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值