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


    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,底层对应代码:

     

           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,对于类类型,工程中尽量使用前置 ++;

  • 相关阅读:
    Linux下的输入/输出重定向
    strcpy与strncpy的区别
    C++的函数重载
    gtest 学习二
    gtest 学习一
    char* wchar* char wchar转换
    iconv 编译不通过问题
    嵌入式常用库
    驱动编程class_create说明
    libiconv 交叉编译
  • 原文地址:https://www.cnblogs.com/dishengAndziyu/p/10913920.html
Copyright © 2020-2023  润新知