为什么前缀++/--比后缀++/--的效率高?

来源:互联网 发布:剑网3英气军娘捏脸数据 编辑:程序博客网 时间:2024/06/02 07:56

首先切记一句话前缀++比后缀++的效率高,返回引用的效率比返回对象的效率高,所以前缀++返回引用,后缀++返回对象。

对于内置类型和当代的编译器而言,这看似不是什么问题。然而,C++允许您针对类定义这些运算符,在这种情况下,用户这样定义前缀函数:将值加1,然后返回结果;但后缀版本首先复制一个副本,将其加1,然后将复制的副本返回。因此,对于类而言,前缀版本的效率比后缀版本高。

总之,对于内置类型,采用哪种格式不会有差别,但对于用户定义的类型,如果有用户定义的递增和递减运算符,则前缀格式的效率更高。

在句法上,重载函数是通过它们的参数类型的差异区分的,但是不管是前缀形式还是后缀形式的自增和自减都没有参数,我们到底该怎么区分它们呢?在开始时,C++在语法上面确实是存在这个问题的,程序员对此颇有微词。后来C++中加了一些特性来解决这个问题。

C++规定后缀形式有一个int类型的参数,当函数被调用时,编译器传递一个0作为int参数的值给该函数。

且看下面的小程序:

#include <iostream> class MyInt{    public:    MyInt(int a):i(a) {   }     MyInt& operator++();            // prefix ++    const MyInt operator++(int);    // postfix ++     MyInt& operator--();            // prefix --    const MyInt operator--(int);    // postfix --     friend std::ostream& operator<<(std::ostream&,const MyInt&);     private:    int i;}; MyInt& MyInt::operator++(){    this->i++;    return *this;} const MyInt MyInt::operator++(int){    const MyInt temp = *this;    ++(*this);    return temp;} std::ostream& operator<<(std::ostream& out,const MyInt& t){    out << t.i ;    return out;} int main(){     MyInt a(0);         a++;     std::cout << a << std::endl; // i = 1,print 1     ++a;     std::cout << a << std::endl; // i = 2,print 2      std::cout << a++ << std::endl; // i = 3,print 2      std:: cout << ++a << std::endl; // i = 4,print 4     return 0;}


 

看上面的程序可以发现以下几点:

1.       后缀形式的参数并没有被用到,它只是语法上的要求,为了区分而已;

2.       后缀形式返回一个const对象;这样做是大有深意滴~~ 我们知道操作符重载本质上是一个函数而已,它应该和操作符原来意义、使用习惯相似,而对于int内置类型来说的话,i++++是有语法错误的,故为了保持一致,重载之后的后缀形式也应该是这样的。假如返回的不是const类型,那么对于

MyInt t(1);

t++++;   // t.operator++(0).operator++(0)

这样的形式将是正确的,这显然不是我们期望的。另外,只要看上面的后缀形式的定义即可知道,这样写t只是增加了1而不是我们期望的2,为什么呢?因为第二次的调用是用第一次返回的对象来进行的,而不是用t,它违反了俺们程序员的直觉。因此,为了阻止这些行为,我们返回const对象。

3.       我们应该尽可能调用前缀形式;为什么呢?看看后缀形式的定义就可以知道,我们定义了一个临时对象,临时对象的创建、析构还是很费时间的。而前缀形式则不一样,它的效率应该相对好一些。

以上就是自增\自减操作符重载的前缀和后缀形式,我们只要记住那个参数规定和返回值形式,就很容易掌握啦



1 0
原创粉丝点击