1,C 语言中讨论了原生含义,C++ 中有必要考虑前置、后置操作符能够重载,有何问题;
2,值得思考的问题:
1,下面的代码有没有区别?为什么?
1,i++ // i 的值作为返回值,i 自增 1;
2,++i // i 自增 1,i 的值作为返回值;
3,没有使用返回值,由于编译器(不同的编译器都是一样的)的优化,在工程上面,这两行代码没有区别;
2,真的有区别吗?编程实验:
1,main.cpp 文件:
#include <iostream>
#include <string> using namespace std; int main()
{
int i = ; i++; ++i; return ;
}
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 文件:
#include <iostream>
#include <string> using namespace std; class Test
{
int mValue;
public:
Test(int i)
{
mValue = i;
} int value()
{
return mValue;
} Test& operator ++ () // ++ 后返回自身;
{
++mValue; // 先将当前操作数加 1; return *this; // 加 1 后返回当前的操作数;
} /* 若这个操作符不实现,则编译器显示:error: no 'operator++(int) declared for poatfix '++', try prefix operator instead */
/* C 语言中定义,如果是后置 ++,它先将当前操作数值保存在临时对象中;于是这里借助局部对象 ret 保存下来,之后返回 */
Test operator ++ (int) // 占位参数为 int 类型;
{
Test ret(mValue);// ++ 之前的值先返回,当然这里先存储着返回值,之后再 ++; mValue++; // 然后 ++ return ret;
}
}; int main()
{
Test t(); t++; ++t; return ;
}
2,上述 main() 中的两行加加代码,因为调用函数不一样,所以有差异,并 且前置 ++ 效率更高,因为它的实现没有生成额外的对象,意味着不需要过 多的栈内存,不需要调用构造、析构函数;
6,真正的区别(本博文2 中的思考):
1,对于基础类型的变量:
1,前置 ++ 的效率与后置 ++ 的效率基本相同;
1,编译器会优化;
2,根据项目组编码规范进行选择;
2,对于类类型的对象:
1,前置 ++ 的效率高于后置 ++;
2,尽量使用前置 ++ 操作符提高程序效率;
7,复数类的进一步完善 class Complex 编程实验:
1,Complex.h 文件:
#ifndef _COMPLEX_H_
#define _COMPLEX_H_ class Complex
{
double a;
double b;
public:
Complex(double a = , double b = );
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);
};
2,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;
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 + ;
b = b + ; return *this;
} Complex Complex::operator ++ (int)
{
Complex ret(a, b); a = a + ;
b = b + ; return ret;
} #endif
8,小结:
1,编译优化使得最终的可执行程序更加高效;
2,前置 ++ 操作符和后置 ++ 操作符都可以被重载;
3,++ 操作符的重载必须符合其原生语义;
4,对于基础类型,前置 ++ 与后置 ++ 的效率几乎相同;
5,对于类类型,前置 ++ 的效率高于后置 ++;
1,对于类类型,工程中尽量使用前置 ++;