zoukankan      html  css  js  c++  java
  • 6. 区别increment/decrement操作符的前置(prefix)和后置(postfix)形式

    C++中允许++ 和-- 操作符的前置和后置两种形式具有重载的能力。而重载是以参数类型来区分的,然而不论是++ 还是 -- 的前置或后置均没有参数,为了区分这两种不同的操作,只好让后置式有一个int自变量,并且在它调用的时候,编译器默认给该int指定一个0值。

    下面的例子是使char型也能进行++ 和 -- 的运算:

    class Char
    {
    public:
        Char(char);
        Char& operator++ ();                 //前置式++
        const Char operator++ (int);         //后置式++
        Char& operator-- ();                 //前置式--
        const Char operator-- (int);         //后置式--
        Char& operator+= (int);              //+=操作符
            //...
    }
    Char C = 'a';
    ++C;                 //调用C.operator++();
    C++;                 //调用C.operator++(int);
    --C;                 //调用C.operator--();
    C--;                 //调用C.operator--(int);

    注意上面前置式和后置式的返回值的不同,仅以++操作符进行阐述:

    C语言中++的前置和后置的区别为:前置式先累加后取出(increment and fetch),后置式先取出后累加(fetch and increment)。我们进行重载时,尽量不改变原来的意义,看看两种操作的实现:

    Char& Char::operator ++()
    {
        (*this) += 1;              //increment
        return *this;              //fetch
    }
    const Char Char::operator ++ (int)
    {
        Char oldValue = *this;     //fetch
        ++(*this);                 //increment
        return oldValue;
    }

    由上序代码就能很回答:

    前置式为什么要返回对象的引用了,因为直接对原对象本身进行了累加并返回自身。

    后置式为什么要返回一个const对象?首先返回值必须是一个对象,这是显然的,因为要返回累加前的对象;其次为什么是const对象呢?如果不是const对象会出现什么情况:

    其一,违反了后置++的运算语法规则:C语言中不允许两次使用后置++操作符,即下面的操作是非法的:

    int i;
    
    i++++;       //error! (但++++i是合法的)

    如果我们返回不是const对象,意味着下面的操作编译器不会报错:

    Char c;
    
    c++++;          //不会报错,调用的动作如下
    
                    //c.operator++(0).operator++(0);

    其二,运算结果不符合我们的预期:假设允许返回是非const对象,那么其运算结果和我们期望的并不相同:

    如上面的代码,第二次operator++ 改变的对象是第一个operator++ 返回的对象,而不是原对象。即经过c++++之后,c的值也只是加了一次而已。这违反了我们的直觉,也违背了我们的意图,因此应该被禁止!


    到这里,++操作符的前置和后置应该比较清楚了,而--操作符完全类似。

    最后,如果仔细观察前置式和后置式,它们除了返回值不同,完成的任务是相同的:将某值累加!如果我们只需要进行累加,很显然使用前置式的效率要比后置式的高,原因有两点:

    • 后置式++调用了前置式++的操作;
    • 后置式要生成一个临时对象存储原值,这中间有拷贝构造和析构的代价,而前置式却没有。

    因此,应该尽可能使用前置式操作!

    参考文献: 《More Effective C++ 35个改善编程与设计的有效方法 中文版》
  • 相关阅读:
    方法返回值使用哪个关键字?
    Java中带参数的方法和JavaScript中带参数的函数有什么不同?
    如何调用方法
    Java中如何声明方法?JavaScript中如何声明函数?
    为什么编程语言中要有方法
    什么叫方法.
    说说字符常量和字符串常量的区别
    什么是JDK?什么是JRE?说说它们之间的区别?
    Go 错误处理
    Go Defer
  • 原文地址:https://www.cnblogs.com/hazir/p/2451933.html
Copyright © 2011-2022 走看看