zoukankan      html  css  js  c++  java
  • 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;
        }
        
  • 相关阅读:
    Java流程控制,用户交互scanner和运算结构
    Day14_Date类
    Day14_BigDecimal的使用
    Day14_StringBuffer和StringBuilder
    Day14_String概述
    装箱、拆箱面试题
    Day14_类型转换与装箱、拆箱
    简单的银行小案例
    Day12_面向对象 异常处理机制
    Day12_面向对象 异常机制
  • 原文地址:https://www.cnblogs.com/bky-hbq/p/13903881.html
Copyright © 2011-2022 走看看