第39课 逗号操作符的分析

1. 逗号操作符(

(1)逗号表达式用于将多个子表达式连接为一个表达式

(2)逗号表达式最后一个子表达式的值

(3)逗号表达式N-1个子表达式可以没有返回值,最后一个要有返回值

(4)逗号表达式按照从左向右的顺序计算每个子表达式的值

        exp1,exp2,exp3,…,expN;

  1 #include <iostream>
  2 
  3 using namespace std;
  4 
  5 void func(int i)
  6 {
  7     cout << "func(): i = " << i << endl;
  8 }
  9 
 10 int main()
 11 {
 12     #include <iostream>
 13 
 14 using namespace std;
 15 
 16 void func(int i)
 17 {
 18     cout << "func(): i = " << i << endl;
 19 }
 20 
 21 int main()
 22 {
 23     int a[3][3] = {
 24          
 25         (0, 1, 2), //注意这里是逗号,不是花括号  表达式值:2
 26 
 27         (3, 4, 5), //相当于只给数组前三个元素赋值   表达式值:5
 28 
 29         (6, 7 ,8)  //分别是2、5、8,其余为0  表达式值:8
 30     };
 31 
 32 /*    int a[3][3] = {   这才是初始化
 33 
 34         {0, 1, 2},
 35 
 36         {3, 4, 5},
 37 
 38         {6, 7 ,8 }
 39     };*/
 40 
 41     int i = 0;
 42     int j = 0;
 43 
 44     while (i < 5)
 45 
 46         func(i),  //这里与下一行的i++组合一个表达式
 47 
 48         i++;          //所以while不会死循环
 49 
 50     等价于while(i < 5)
 51         {
 52             func(i);
 53             i++;
 54         }
 55 
 56 
 57     for (int i = 0; i < 3; i++)
 58     {
 59         for (int j = 0; j < 3; j++)
 60         {
 61             cout << a[i][j] << endl; //2,5,8,0,0,0,0,0,0
 62         }
 63     }
 64 
 65     (i, j) = 6; //合法:逗号表达式返回j,相当于j = 6
 66 
 67     cout << "i = " << i << endl;  //5
 68 
 69     cout << "j = " << j << endl;  //6
 70 
 71 
 72 
 73     return 0;
 74 
 75 }
 76 
 77     int i = 0;
 78     int j = 0;
 79 
 80     while (i < 5)
 81 
 82         func(i),  //这里与下一行的i++组合一个表达式
 83 
 84         i++;          //所以while不会死循环
 85 
 86     等价于while(i < 5)
 87         {
 88             func(i);
 89             i++;
 90         }
 91 
 92 
 93     for (int i = 0; i < 3; i++)
 94     {
 95         for (int j = 0; j < 3; j++)
 96         {
 97             cout << a[i][j] << endl; //2,5,8,0,0,0,0,0,0
 98         }
 99     }
100 
101     (i, j) = 6; //合法:逗号表达式返回j,相当于j = 6
102 
103     cout << "i = " << i << endl;  //5
104 
105     cout << "j = " << j << endl;  //6
106 
107 
108 
109     return 0;
110 
111 }

运行结果:

  

2. 重载逗号操作符

(1)在C++中重载逗号操作符合法

(2)使用全局函数对逗号操作符进行重载

(3)重载函数参数必须有一个是类类型(因为这里指的是类的操作符重载)

(4)重载函数返回值类型必须是引用

ClassType& operator ,(const ClassType& a, const ClassType& b)    全局函数进行重载
{

    return const_cast<ClassType&>(b); //逗号表达式,返回右操作符,必须强制转换,函数返回值是引用,所以去除const属性

}
 1 #include<iostream> 
 2 #include<string>
 3 
 4 using namespace std;
 5 
 6 //重载需要类类型,定义类
 7 class Test
 8 {
 9     int mvalue;
10 public:
11     Test(int i)
12     {
13         mvalue = i;
14     }
15     int value()
16     {
17         return mvalue;
18     }
19 };
20 
21 //全局函数进行逗号操作符重载
22 Test& operator , (const Test& a, const Test& b) // 1、参数必须有一个为类类型
23 {
24     return const_cast<Test&>(b);   //2,返回值是Test引用,所以要强制类型转换去掉const属性
25 }
26 
27 Test func(Test& i)   //
28 {
29     cout << "func() : i = " << i.value() << endl;
30 
31     return i;
32 }
33 
34 int main()
35 {
36     Test t0(0);
37     Test t1(1);
38 
39 //  Test tt=(t0,t1);  //逗号表达式,等价于Test tt=t1;
40 
41     //为什么先调用右边????逗号操作符重载中间发生变化,变成从右向左调用,违背逗号表达式
42 
43     //因重载操作符的本质相当于函数调用,所以
44 
45     //相当于Test tt = operator,(func(t0(0)), func(t1(1)));//函数调用!
46 
47     //当进入函数体,参数的值必须被计算,而两个参数func(t0(0))和func(t1(1))
48 
49     //的计算次序是不确定的,在g++编译下,输出
50 
51     //func(): i = 1
52 
53     //func(): i = 0
54     
55     Test tt = (func(t0), func(t1));   //逗号表达式,等价于Test tt=func(t1); 逗号表达式,本意是从左向右计算
56                                     
57 
58                                     
59   //  Test tt = (operator , (func(t0), func(t1)));                                                                    //等价于Test tt = (operator , func(t0), func(t1));  
60 
61     cout << tt.value() << endl; //1虽然结果是正确的,但中间的计算过程与
62 
63                                 //逗号表达式原义从左向右计算要求有可能不一致。
64 
65     return 0;
66 }

3. 重载时出现的问题与本质分析

(1)C++通过函数调用扩展操作符的功能

(2)进入函数体前必须完成所有参数的计算

(3)函数参数的计算次序是不定的

(4)重载后无法严格从左向右计算表达式,不重载时返回能从左向右,所以重载逗号操作符完全无意义,违背逗号表达式原生语义

 实验:工程中,完全没有必要重载逗号操作符

 1 #include<iostream> 
 2 #include<string>
 3 using namespace std;
 4 //全局函数进行逗号操作符重载
 5 
 6 class Test
 7 {
 8     int mvalue;
 9 public:
10     Test(int i)
11     {
12         mvalue = i;
13     }
14     int value()
15     {
16         return mvalue;
17     }
18 };
19 
20 //不要进行逗号操作符重载
21 /*
22 Test& operator , (const Test& a, const Test& b)
23 {
24     return const_cast<Test&>(b);                 //返回值是Test 引用,所以要强制类型转换去掉const属性,用const_cast
25 }
26 */
27 
28 Test func(Test& i)
29 {
30     cout << "func() : i = " << i.value() << endl;
31     return i;
32 }
33 
34 int main()
35 {
36     Test t0(0);
37     Test t1(1);
38      
39     Test tt = (func(t0), func(t1));        
40                                                                     
41 //    Test tt = (operator , (func(t0), func(t1)));                                                            
42 
43     cout << tt.value() << endl;      //func(): i=0
44                                      //func(): i=1
45 
46     去掉重载,结果与没有重载之前结果一致--------------工程中,完全没有必要重载逗号操作符
47 
48     return 0;
49 }

4. 小结

(1)逗号表达式从左向右顺序计算每个子表达式的值

(2)逗号表达式最后一个子表达式的值

(3)操作符重载无法完全实现逗号操作符的原生意义从左向右计算

(4)工程开发中不要重载逗号操作符

原文地址:https://www.cnblogs.com/liuyueyue/p/13382933.html