欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C++中前置操作符和后置操作符的重载

程序员文章站 2022-04-18 09:46:22
1,C 语言中讨论了原生含义,C++ 中有必要考虑前置、后置操作符能够重载,有何问题; 2,值得思考的问题: 1,下面的代码有没有区别?为什么? 1,i++ // i 的值作为返回值,i 自增 1; 2,++i // i 自增 1,i 的值作为返回值; 3,没有使用返回值,由于编译器(不同的编译器都 ......

1,c 语言中讨论了原生含义,c++ 中有必要考虑前置、后置操作符能够重载,有何问题;

 

2,值得思考的问题:

    1,下面的代码有没有区别?为什么?

       1,i++  // i 的值作为返回值,i 自增 1;

       2,++i  // i 自增 1,i 的值作为返回值;

       3,没有使用返回值,由于编译器(不同的编译器都是一样的)的优化,在工程上面,这两行代码没有区别;

    2,真的有区别吗?编程实验:

       1,main.cpp 文件:

 1 #include <iostream>
 2 #include <string>
 3 
 4 using namespace std;
 5 
 6 int main()
 7 {
 8     int i = 0;
 9 
10     i++;
11 
12     ++i;
13 
14     return 0;
15 }

  2,底层对应代码:

 C++中前置操作符和后置操作符的重载

       1,工程上除了使用的寄存器有差别之外,本质没有什么差别;

       2,这是由于编译器的优化,这里是单独存在的、并没有使用它们的返回值,这个时候编译器的优化就是将返回值抛弃,得到的汇编代码就是上述内容;

      

3,现代编译器中的自增特性:

    1,现代编译器产品会对代码进行优化;

    2,优化使得最终的二进制程序更加高效;

    3,优化后的二进制程序丢失了 c/c++ 的原生语义;

    4,不可能从编译后的二进制程序还原 c/c++ 程序;

   

4,思考:

    1,++ 操作符可以重载吗?如何区分前置 ++ 和后置 ++ ?

       1,可以,-- 操作符也可以;

   

5,++ 操作符重载:

    1,++ 操作符可以被重载:

       1,全局函数和成员函数局可以进行重载;

       2,重载前置 ++ 操作符不需要额外的参数;

       3,重载后置 ++ 操作符需要一个 int 类型的占位参数;

    2,++ 操作符的重载编程实验:

       1,main.cpp 文件:

 1 #include <iostream>
 2 #include <string>
 3 
 4 using namespace std;
 5 
 6 class test
 7 {
 8     int mvalue;
 9 public:
10     test(int i)
11     {
12         mvalue = i;
13     }
14     
15     int value()
16     {
17         return mvalue;
18     }
19     
20     test& operator ++ ()  // ++ 后返回自身;
21     {
22         ++mvalue;  // 先将当前操作数加 1;
23          
24         return *this;  // 加 1 后返回当前的操作数;
25     }
26     
27     /* 若这个操作符不实现,则编译器显示:error: no 'operator++(int) declared for poatfix '++', try prefix operator instead */
28     /* c 语言中定义,如果是后置 ++,它先将当前操作数值保存在临时对象中;于是这里借助局部对象 ret 保存下来,之后返回 */
29     test operator ++ (int)  // 占位参数为 int 类型;
30     {
31         test ret(mvalue);// ++ 之前的值先返回,当然这里先存储着返回值,之后再 ++;
32         
33         mvalue++;  // 然后 ++
34         
35         return ret;
36     }
37 };
38 
39 int main()
40 {
41     test t(0);
42     
43     t++;  
44     
45     ++t;
46     
47     return 0;
48 }

  2,上述 main() 中的两行加加代码,因为调用函数不一样,所以有差异,并 且前置 ++ 效率更高,因为它的实现没有生成额外的对象,意味着不需要过  多的栈内存,不需要调用构造、析构函数;

      

6,真正的区别(本博文2 中的思考):

    1,对于基础类型的变量:

       1,前置 ++ 的效率与后置 ++ 的效率基本相同;

           1,编译器会优化;

       2,根据项目组编码规范进行选择;

    2,对于类类型的对象:

       1,前置 ++ 的效率高于后置 ++;

       2,尽量使用前置 ++ 操作符提高程序效率;

      

7,复数类的进一步完善 class complex 编程实验:

    1,complex.h 文件: 

 1 #ifndef _complex_h_
 2 #define _complex_h_
 3 
 4 class complex
 5 {
 6     double a;
 7     double b;
 8 public:
 9     complex(double a = 0, double b = 0);
10     double geta();
11     double getb();
12     double getmodulus();
13     
14     complex operator + (const complex& c);
15     complex operator - (const complex& c);
16     complex operator * (const complex& c);
17     complex operator / (const complex& c);
18     
19     bool operator == (const complex& c);
20     bool operator != (const complex& c);
21     
22     complex& operator = (const complex& c);
23     
24     /* 本博文重载了下面两个操作符 */
25     complex& operator ++ ();
26     complex operator ++ (int);
27 };

 2,complex.cpp 文件:

  1 #include "complex.h"
  2 #include "math.h"
  3 
  4 complex::complex(double a, double b)
  5 {
  6     this->a = a;
  7     this->b = b;
  8 }
  9 
 10 double complex::geta()
 11 {
 12     return a;
 13 }
 14 
 15 double complex::getb()
 16 {
 17     return b;
 18 }
 19 
 20 double complex::getmodulus()
 21 {
 22     return sqrt(a * a + b * b);
 23 }
 24 
 25 complex complex::operator + (const complex& c)
 26 {
 27     double na = a + c.a;
 28     double nb = b + c.b;
 29     complex ret(na, nb);
 30     
 31     return ret;
 32 }
 33 
 34 complex complex::operator - (const complex& c)
 35 {
 36     double na = a - c.a;
 37     double nb = b - c.b;
 38     complex ret(na, nb);
 39     
 40     return ret;
 41 }
 42 
 43 complex complex::operator * (const complex& c)
 44 {
 45     double na = a * c.a - b * c.b;
 46     double nb = a * c.b + b * c.a;
 47     complex ret(na, nb);
 48     
 49     return ret;
 50 }
 51 
 52 complex complex::operator / (const complex& c)
 53 {
 54     double cm = c.a * c.a + c.b * c.b;
 55     double na = (a * c.a + b * c.b) / cm;
 56     double nb = (b * c.a - a * c.b) / cm;
 57     complex ret(na, nb);
 58     
 59     return ret;
 60 }
 61     
 62 bool complex::operator == (const complex& c)
 63 {
 64     return (a == c.a) && (b == c.b);
 65 }
 66 
 67 bool complex::operator != (const complex& c)
 68 {
 69     return !(*this == c);
 70 }
 71     
 72 complex& complex::operator = (const complex& c)
 73 {
 74     if( this != &c )
 75     {
 76         a = c.a;
 77         b = c.b;
 78     }
 79     
 80     return *this;
 81 }
 82 
 83 complex& complex::operator ++ ()
 84 {
 85     a = a + 1;
 86     b = b + 1;
 87     
 88     return *this;
 89 }
 90     
 91 complex complex::operator ++ (int)
 92 {
 93     complex ret(a, b);
 94     
 95     a = a + 1;
 96     b = b + 1;
 97     
 98     return ret;
 99 }
100 
101 #endif

 

8,小结:

    1,编译优化使得最终的可执行程序更加高效;

    2,前置 ++ 操作符和后置 ++ 操作符都可以被重载;

    3,++ 操作符的重载必须符合其原生语义;

    4,对于基础类型,前置 ++ 与后置 ++ 的效率几乎相同;

    5,对于类类型,前置 ++ 的效率高于后置 ++;

       1,对于类类型,工程中尽量使用前置 ++;