今天来学习C++中的逗号操作符。那么什么是逗号操作符呢?
*逗号操作符(,)可以构成逗号表达式
- 逗号表达式用于将多个子表达式连接为一个表达式
- 逗号表达式的值为最后一个子表达式的值
- 逗号表达式的前N-1个表达式的值可以没有返回值
逗号表达式按照从左向右的顺序计算每个表达式的值
exp1,exp2,……,expn-1,expn
下面我们还是以一个例子来说明逗号表达式概念与性质:
#include <iostream>
#include <string>
using namespace std;
void func(int i)
{
cout << "func() : i = " << i << endl;
}
int main()
{
int a[3][3]={
(0,1,2), //注意,这里的二维数组的初始化用的是(),而不是{},所以里面的内容构成逗号表达式(0,1,2)的值就为2.
(3,4,5), //(3,4,5)的值为5
(6,7,8) //(6,7,8)的值为8,所以这个数组实际上,只初始化了前三个数,后面的数全为0;
};
int i = 0;
int j = 0;
while(i < 5)
func(i), /*注意这里是逗号,而不是分号,所以这个表达式等同于{func(i);i++}*/
i++;
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
cout << a[i][j] << endl;
}
}
(i,j) = 6; //此处给逗号表达式赋值,实际上是给j赋值,而i值不变
cout << "i = " << i << endl;
cout << "j = " << j << endl;
return 0;
}
上述程序运行结果为:
func() : i = 0
func() : i = 1
func() : i = 2
func() : i = 3
func() : i = 4
2
5
8
0
0
0
0
0
0
i = 3
j = 6
由运行结果,以及程序内容的分析,得以验证上面所说的逗号表达式的性质。
那么,我们来试一下逗号表达式的重载,看看会出现什么结果:
#include <iostream>
#include <string>
using namespace std;
class Test
{
int mValue;
public:
Test(int i)
{
mValue = i;
}
int Value()
{
return mValue;
}
};
Test func(Test& i)
{
cout << "func() : i = " << i.Value() << endl;
return i;
}
Test& operator , (const Test& a, const Test& b) //重载逗号操作符
{
return const_cast<Test&>(b);
}
int main()
{
Test t0(0);
Test t1(1);
Test tt = (func(t0),func(t1));
cout << tt.Value() << endl;
return 0;
}
运行结果:
func() : i = 1
func() : i = 0
1
由程序的分析,以及运行结果得知,我们的逗号操作符确实是返回的是最后一个子表达式的值,但是有一点,却变了,子表达式的运行的次序,可以看出,是先运行func(t1),后运行func(t0),这是为什么呢?
问题本质的分析:
- C++通过函数调用扩展操作符的功能
- 进入函数体前必须完成所有参数的计算
- 函数参数的计算次序是不定的
- 重载后无法严格按照从左向右的次序计算表达式(这跟编译器有关,也有可能会从左向右计算)
而当我们把上面的重载函数去掉,不用重载的逗号表达式,直接用原有的逗号表达式,结果就是:
func() : i = 0
func() : i = 1
1
总结:
- 逗号表达式从左向右计算子表达式的值
- 逗号表达式的值为最后一个子表达式的值
- 操作符重载无法实现逗号操作符的原生语义
- 工程开发中不要重载逗号操作符
想一起探讨以及获得各种学习资源加我(有我博客中写的代码的原稿):
qq:1126137994
微信:liu1126137994
可以共同交流关于嵌入式,操作系统,C++语言,C语言,数据结构等技术问题。