30 前置操作符和后置操作符

1 问题

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

    • 在工程上没有区别,编译器进行了优化
    i++;  // i的值作为返回值,i自增1
    ++i;  // i自增1,i的值作为返回
    
  • 示例1:i++++i 的区别

    • Demo

      #include <iostream>
      #include <string>
      
      using namespace std;
      
      int main()
      {
          int i = 0;
      
          i++;
      
          ++i;
      
          return 0;
      }
      
    • VS 汇编代码:相同,只有使用的寄存器不同而已 => 在忽略返回值的情况下

      #include <iostream>
      #include <string>
      
      using namespace std;
      
      int main()
      {
      000E1C70  push        ebp  
      000E1C71  mov         ebp,esp  
      000E1C73  sub         esp,0CCh  
      000E1C79  push        ebx  
      000E1C7A  push        esi  
      000E1C7B  push        edi  
      000E1C7C  lea         edi,[ebp-0CCh]  
      000E1C82  mov         ecx,33h  
      000E1C87  mov         eax,0CCCCCCCCh  
      000E1C8C  rep stos    dword ptr es:[edi]  
      000E1C8E  mov         ecx,offset _2F191172_main@cpp (0EC02Ah)  
      000E1C93  call        @__CheckForDebuggerJustMyCode@4 (0E128Fh)  
      	int i = 0;
      000E1C98  mov         dword ptr [i],0    //将0放到标识符i对应的4个字节的内存中
      
      	i++;
      000E1C9F  mov         eax,dword ptr [i]  //将标识符i所对应的内存中的值传到eax寄存器中
      000E1CA2  add         eax,1              //将eax寄存器中的值加1
      000E1CA5  mov         dword ptr [i],eax  //将eax寄存器中的值传到标识符i所对应的内存中去
      
      	++i;
      000E1CA8  mov         eax,dword ptr [i]  
      000E1CAB  add         eax,1  
      000E1CAE  mov         dword ptr [i],eax  
      
      	return 0;
      000E1CB1  xor         eax,eax  
      }
      000E1CB3  pop         edi  
      000E1CB4  pop         esi  
      000E1CB5  pop         ebx  
      000E1CB6  add         esp,0CCh  
      000E1CBC  cmp         ebp,esp  
      000E1CBE  call        __RTC_CheckEsp (0E1299h)  
      000E1CC3  mov         esp,ebp  
      000E1CC5  pop         ebp  
      000E1CC6  ret 
      
  • 分析

    • 现代编译器会对代码进行优化
    • 优化使得最早的二进制程序更加高效
    • 优化后的二进制程序丢失了 C/C++ 的原生语义
    • 不可能从编译后的二进制程序还原 C/C++ 程序

2 重载 ++ 操作符

  • 【问题】++ 操作符可以重载么?如何区分前置 ++ 和后置 ++

  • ++ 操作符可以被重载

    • 全局函数成员函数(推荐)均可进行重载
    • 重载前置 ++ 操作符不需要额外的参数
    • 重载后置 ++ 操作符需要一个 int 类型的占位参数
  • 实例2:++ 操作符的重载

    • Demo

      #include <iostream>
      #include <string>
      
      using namespace std;
      
      class Test
      {
          int mValue;
      public:
          Test(int i)
          {
              mValue = i;
          }
          
          int value()
          {
              return mValue;
          }
          
          // 成员函数进行前置++操作符重载,返回类引用,没有在栈上生成额外的对象
          Test& operator ++ ()
          {
              ++mValue;      
              return *this;
          }
          
          // 成员函数进行后置++操作符重载,返回局部变量
          Test operator ++ (int)
          {
              Test ret(mValue);  // 在栈上创建对象,需要调用构造函数、析构函数 
              mValue++;  
              return ret;
          }
      };
      
      int main()
      {
          Test t(0);
          Test t1(0);
          cout << t.value() << endl;   // 0
          cout << t1.value() << endl;  // 0
          
          Test tt = t++;
          cout << t.value() << endl;   // 1
          cout << tt.value() << endl;  // 0
          
          Test tt1 = ++t1;
          cout << t1.value() << endl;  // 1
          cout << tt1.value() << endl; // 1
          
          return 0;
      }
      
  • ++ 前置和后置真正的区别

    • 对于基础类型的变量

      • 前置 ++ 的效率和后置 ++ 的效率基本相同
      • 根据项目组编码规范进行选择
    • 对于类类型的对象

      • 前置 ++ 的效率高于后置 ++ :前置 ++ 返回类引用,没有生成额外的对象,后置返回局部的类对象
      • 尽量使用前置 ++ 操作符提高程序效率
  • 复数类 Complex 的进一步完善

    • Demo

      // Complex.h
      #ifndef COMPLEX_H_
      #define _COMPLEX_H_
      
      class Complex
      {
          double a;
          double b;
      public:
          Complex(double a = 0, double b = 0);
          double getA();
          double getB();
          double getModulus();
          
          Complex operator + (const Complex& c);
          Complex operator - (const Complex& c);
          Complex operator * (const Complex& c);
          Complex operator / (const Complex& c);
          
          bool operator == (const Complex& c);
          bool operator != (const Complex& c);
          
          Complex& operator = (const Complex& c);
          
          // 重载++操作符
          Complex& operator ++ ();
          Complex operator ++ (int);
      };
      
      #endif
      
      
      //Complex.cpp
      #include <cmath>
      #include "Complex.h"
      
      Complex::Complex(double a, double b)
      {
          this->a = a;
          this->b = b;
      }
      
      double Complex::getA()
      {
          return a;
      }
      
      double Complex::getB()
      {
          return b;
      }
      
      double Complex::getModulus()
      {
          return sqrt(a * a + b * b);
      }
      
      Complex Complex::operator + (const Complex& c)
      {
          double na = a + c.a;
          double nb = b + c.b;
          Complex ret(na, nb);
          
          return ret;
      }
      
      Complex Complex::operator - (const Complex& c)
      {
          double na = a - c.a;
          double nb = b - c.b;
          Complex ret(na, nb);
          
          return ret;
      }
      
      Complex Complex::operator * (const Complex& c)
      {
          double na = a * c.a - b * c.b;
          double nb = a * c.b + b * c.a;
          Complex ret(na, nb);
          
          return ret;
      }
      
      Complex Complex::operator / (const Complex& c)
      {
          double cm = c.a * c.a + c.b * c.b;
          double na = (a * c.a + b * c.b) / cm;
          double nb = (b * c.a - a * c.b) / cm;
          Complex ret(na, nb);
          
          return ret;
      }
          
      bool Complex::operator == (const Complex& c)
      {
          return (a == c.a) && (b == c.b);
      }
      
      bool Complex::operator != (const Complex& c)
      {
          return !(*this == c);
      }
          
      Complex& Complex::operator = (const Complex& c)
      {
          if( this != &c )
          {
              a = c.a;
              b = c.b;
          }
          
          return *this;
      }
      
      // 重载前置++操作符
      Complex& Complex::operator ++ ()
      {
          a = a + 1;
          b = b + 1;
          
          return *this;
      }
      
      // 重载后置++操作符
      Complex Complex::operator ++ (int)
      {
          Complex ret(a, b);
          
          a = a + 1;
          b = b + 1;
          
          return ret;
      }
      
    • 应用

      #include <iostream>
      #include "Complex.h"
      
      using namespace std;
      
      int main()
      {
          Complex c(0,0);
          Complex b = ++c;
          Complex b1 = c++;
      
          cout << b.getA() << endl;   // 1
          cout << b.getB() << endl;   // 1
          
          cout << b1.getA() << endl;  // 0
          cout << b1.getB() << endl;  // 0
      
          return 0;
      }
      
原文地址:https://www.cnblogs.com/bky-hbq/p/13903881.html