More Effetive C++(条款6:区别increment/decrement操作符的前置(prefix)和后置(postfix)形式)

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

例:

class Char
{
public:
    Char& operator++ ();                 //前置式++,返回类型:引用
    const Char operator++ (int);         //后置式++,返回类型:const临时对象
    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);

2、前置式返回调用它的对象的引用:后置式返回const 临时对象:

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的值也只是加了一次而已。这违反了我们的直觉,也违背了我们的意图,因此应该被禁止!

c++中有一条原则就是“绝对不让用户更改临时对象”(异常处理除外),因为临时对象是由编译器产生的,我们无法主动使用,同时它的生存期也无法由我们来掌握,所以除了用临时对象来充当传入参数或返回值的"载体"外,任何对临时对象的更改都是无意义的,也就被编译器严厉禁止。

让后置式返回const对象,可禁止上述行为。

i++++;//视同i.operator++(0).operator++(0);
 

第一次调用operator++返回的const对象,将被用来进行operator++的第二次调用。而const对象不能调用非常量成员函数,故无法调用。

3、由于后自增要创建一个临时对象保存之前对象的副本,所以比前自增效率要低,在两者效果相同的情况下推荐使用前自增

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

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

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



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值