一、i++和++i有没有区别?
1.现代编译器产品会对代码进行优化
2.优化使得最终二进制程序更加高效
3.优化后的二进制程序丢失了c/c++的原生语义
4.不可能从编译后的二进制程序还原c/c++程序
//由此可知,单行的i++和++i在汇编层的代码完全一样
int i = 0; 0123136E mov dword ptr [i],0 i++; 01231375 mov eax,dword ptr [i] 01231378 add eax,1 0123137B mov dword ptr [i],eax ++i; 0123137E mov eax,dword ptr [i] 01231381 add eax,1 01231384 mov dword ptr [i],eax
二、++操作符的重载
1、全局函数和成员函数均可进行重载
2、重载前置++操作符不需要额外的参数
3、重载后置的++操作符需要一个int类型的占位参数(编译器以此来分辨是前置还是后置操作符)
#include<iostream> using namespace std; class Test { private: int m_value; public: Test(int i) { m_value = i; } int Value() { return m_value; } //前置操作符,原生语义先自增,再将自增后的值作为返回值
//返回值为引用,无参数 Test& operator ++ () { ++m_value; return *this; }
//后置操作符,原生语义为先返回值,再增1
//返回值为对象,有一个int类型的占位参数 Test operator ++ (int) { Test ret(m_value);//先保存原来的值,需要另外创建对象,所有在这里比前置操作符效率低
m_value++;//后自增
return ret; } }; int main() { Test t0(0); Test t1(1); cout<< (t0++).Value() <<endl; //0 cout<< t0.Value() <<endl; //1 cout<< (++t1).Value() <<endl; //2 return 0; }
三、真正的区别
1、对于基础类型的变量
(1)、前置++的效率与后置++的效率基本相同
(2)、根据项目组编程规范进行选择
2、对于类类型的变量
(1)、前置++的效率高于后置++
(2)、尽量使用前置++操作符提高程序效率
四、复数类的进一步完善
//Complex.h
#ifndef _COMPLEX_H_ #define _COMPLEX_H_ class Complex { private: 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 "Complex.h" #include <math.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; return Complex(na, nb);//生成返回值对象然后返回 } Complex Complex::operator - (const Complex& c) { double na = a - c.a; double nb = b - c.b; return Complex(na, nb); } Complex Complex::operator * (const Complex& c) { double na = a * c.a - b * c.b; double nb = a * c.b - b * c.a; return Complex(na, nb); } 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; return Complex(na, nb); } bool Complex::operator == (const Complex& c) { return (a == c.a) && (b = c.b); } bool Complex::operator != (const Complex& c) { //整个复数对象就两个成员,如果这个2个对象的 //内存完全相等时,则两个复数相等 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; }
//main.cpp
#include <stdio.h> #include "Complex.h" int main() { Complex c1(0, 0); Complex t1 = c1++; Complex t2= ++c1; printf("t1.a = %f, t1.b = %f ",t1.getA(), t1.getB());//0, 0 printf("t2.a = %f, t2.b = %f ",t2.getA(), t2.getB());//2, 2 return 0; }
五、小结
1、编译优化使得最终可执行程序更加高效
2、前置操作符和后置操作符都可以重载
3、++操作符的重载必须符合它的原生语义
4、对于基础类型,前置++与后置++效率几乎相同
5、对于类类型,前置++效率高于后置++