第40课 前置操作符和后置操作符
Posted liuyueyue
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第40课 前置操作符和后置操作符相关的知识,希望对你有一定的参考价值。
工程上没有区别,编译器会进行优化,i++,++i并没有返回返回值
【编程实验】真的有区别吗? 40-1.cpp
int i = 0; 013612FB mov dword ptr [i],0 0立即数放在i对应的4字节的内存 i++; 01361302 mov eax,dword ptr [i] i的值存放在eax寄存器 01361305 add eax,1 eax寄存器值+1 01361308 mov dword ptr [i],eax eax寄存器值+1的值,传到 i对应的内存
++i;
0136130B mov ecx,dword ptr [i]
0136130E add ecx,1
01361311 mov dword ptr [i],ecx
底层二进制代码一样,本质一样
1. ++i和i++真的有区别吗?
(1)现代编译器会对代码进行优化
- 对于基础类型,前置++和后置++的汇编代码几乎是一样的,最终效率完全一样。
(2)优化使得最终的二进制程序更加高效
(3)优化后的二进制程序丢失了C/C++的原生语义
(4)不可能从编译后的二进制程序还原C/C++程序
问题:
2. ++(--)操作符的重载
(1)可利用全局函数和成员函数进行重载-----------推荐成员函数
(2)重载前置++操作符(如++i)不需要额外的参数
(3)重载后置++操作符(如i++)需要一个int类型的占位参数(即编译器通过有无这个占位符来区别是重载前置还是后置++操作符)------区分前置++和后置++
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 int value() 15 { 16 return mvalue; //返回成员变量值 17 } 18 19 //推荐全局函数重载 20 // void operator ++ () 原生++t ,返回值是+1后的操作数自身,所以返回值void换回Test& ++t之后返回t自身 21 22 Test& operator ++ () //前置++,不需额外参数 效率高,没有生成额外对象 返回值是引用将t对象返回 23 { 24 ++mvalue; //1,当前操作数+1 25 26 return *this; //2,返回当前操作数自身 27 } 28 29 30 // void operator ++ (int) 原生t++ ,返回值操作数自身后,再+1, 返回++之前的值 31 32 Test operator ++ (int ) //后置++,包括一个int型占位参数 先将当前操作数的值保存在临时对象ret,借助局部返回值对象,值为++之前的 33 { 34 Test ret(mvalue); //1,返回值对象:++之前的值---------调用构造函数 35 36 mvalue++; //2,执行++ 37 38 return ret; //--------调用析构函数 39 } 40 }; 41 42 //为什么后置t++返回值不是引用???? 43 先保存当前操作数的值,保存在临时对象ret 44 45 /* 46 ++i: i自增1,i+1的值作为返回值 47 i++: i的值作为返回值,i自增1 48 */ 49 50 int main() 51 { 52 Test t(0); 53 Test t3(0); 54 55 cout << t.value() << endl; //0 56 57 // ++t; 58 // 59 // cout << t.value() << endl; //1 60 61 Test tt = ++t; 62 63 cout << t.value() << endl; //1 64 cout <<tt.value() << endl; //1 65 66 67 Test t3 = t++; //t对象的值返回值=0对t2进行初始化,然后t后置++将t=1 68 69 cout << t.value() << endl; //1 70 cout << t3.value() << endl; //0 71 72 73 return 0; 74 }
3. 真正的区别-------------看i的类型
(1)对于基础类型的变量
①前置++的效率与后置++的效率基本相同(汇编代码相同,只是寄存器不同)
②根据项目组编码规范进行选择
(2)对于类类型的对象
两个完全不同
①前置++的效率高于后置++(前置++没有生成额外对象,既不需要内存,不需要在栈上生成新的对象,不需要调用构造函数,析构函数,节俭了栈空间)
②尽量使用前置++操作符提高程序效率
【编程实验】复数类的进一步完善 Complex
//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); //后置++ 带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; //实部+1 b = b + 1; //虚部+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; }
运行结果:
4. 小结
(1)编译优化使得最终的可执行程序更加高效
(2)前置++操作符和后置++操作符都可以被重载
(3)++操作符的重载必须符合其原生语义(即前置就先取值再自增,后置应先自增再取值)
(4)对于基础类型,前置++与后置++的效率几乎相同
(5)对于类类型,前置++的效率高于后置++
以上是关于第40课 前置操作符和后置操作符的主要内容,如果未能解决你的问题,请参考以下文章