逗号操作符?C++里有逗号操作符么?
不少C++ newbie都会问到这问题,大家对+-*/自然是认识的了,对其他的%!&|之类的也不觉得陌生,但是逗号操作符?可能有一半的人会说不清楚它到底是干啥的。
其实,我们是经常会用到逗号操作符的,但是并不是所有代码里出现的逗号都是逗号操作符。
让我们先从一个类的示例代码开始:
1:
2: class mynum
3: {
4: public:
5: mynum(double ndb,...)
6: {
7: //init with arguments
8: }
9: };
10: class someclass
11: {
12: someclass():
13: num(3,4)
14: ,a(0)
15: ,b(0)
16: ,c(15)
17: {
18: int i,j;
19: i=1,2; //int x=1,2;
20: for(;b<10;++b,--c)
21: {
22: ++a;
23: }
24: }
25: mynum num;
26: int a;
27: int b,c;
28: };
在这段代码里,逗号在5,13-16,18-20,27行都出现了。
现在先让我们来看看逗号操作符是啥意思:
一个包含逗号的表达式首先计算逗号左边的表达式,然后计算逗号右边的表达式;整个表达式的结果是逗号右边表达式的值。
然后我们看看上面的代码:
第5行是在mynum类的构造函数里出现的逗号,只是用来区分开第一个double类型的参数和后面的可变参数。这是一个特例,如果在构造mynum对象的时候,本来是要传入3.4作为第一个参数的,结果不小心把小数点变成了逗号的话,3.4就变成了两个参数3和4——比如在第13行的情况。类似这样的情况编译器不会报错,程序也能运行,但是mynum类里的成员变量可能就因为构造函数传入的变量值变化而导致程序运行结果完全不一致了。这两个逗号都不是逗号操作符了。
第14,15,16行的逗号,也不是逗号操作符。这三个逗号只是用来间隔构造函数的成员变量初始化列表。
第18行的int i,j;是大家都很常用的变量声明的语句,逗号在这里,也只是起了一个间隔变量声明的作用,也不是逗号运算符。
第19行的逗号,如果不认识逗号操作符的话,一定会认为这肯定是写错了!其实这正是逗号操作符了。让我们看看,经过i=1,2;这个语句后,i 的值应该是多少呢?按照之前逗号操作符的定义,我们好像可以很轻松的得出i=2。然而,这个答案是错的!你在得出错误答案的时候,忽略了一个重要的因素——运算符优先级!由于=号的优先级更高,所以i=1,2;这个语句相当于(i=1),2; ,如果要得到期望的2,我们应该这样来写i=(1,2);。下面的代码可以验证这个说法的(注意第3行是无意义代码,但是可不是错误代码哦!)
1: int i,j;
2: i=1,2;
3: 3,4;
4: j=(1,2);
5: printf("%d\n%d\n",i,j);
继续看第一份代码里的第20行,这是一个for循环代码。这里的逗号,也是逗号操作符哦。其实for循环也是逗号操作符经常出现的地方哦。for循环里只能写一个表达式,而逗号表达式这个时候就可以让你完成两个甚至多个表达式的计算。比如“for(;b<10;++b,--c)”,++b和--c就会在每次循环中都被执行到。
第27行就无须多说了。也就是一普通的变量声明语句,这里的逗号也不是逗号操作符的。
总的来说,逗号操作符并不是一个非常常用的操作符,它只在某些特定的上下文环境里会有很好的效果,同时,在编码中还要非常小心错误的输入的逗号引发错误的问题。
比如逗号和括号就会引发一些潜在问题,如果在编码的时候一疏忽就会产生一些难以追查的隐藏bug,只有遵守一些既定的编码规范,养成良好严谨的编码习惯,才有助于避免一些诸如此类的问题出现。看看下面的代码:
1: int myadd(int i,int j,int k)
2: {
3: return i+j+k;
4: }
5: int myadd(int i,int j)
6: {
7: return i+j;
8: }
9:
10: int main()
11: {
12:
13: for(int x=0;x<9;++x)
14: {
15: printf("%d",myadd((2,3),4));
16: }
17: }
由于在第15行,错误的添加了括号(在实际编码中这样的情况太常见了),结果导致整个的输出全错了!因为(2,3)这个逗号表达式的返回值是3,所以15行相当于是myadd(3,4)了!
so,一定要记住啦,小心,小心,再小心!^_^