翻译《有关编程、重构及其他的终极问题?》——29.在迭代器上请使用前置自增操作符(++i),不要使用后置自增操作符(i++)

翻译《有关编程、重构及其他的终极问题?》——29.在迭代器上请使用前置自增操作符(++i),不要使用后置自增操作符(i++)

标签(空格分隔):翻译 技术 C/C++
作者:Andrey Karpov
翻译者:顾笑群 - Rafael Gu
最后更新:2017年07月15日


29.在迭代器上请使用前置自增操作符(++i),不要使用后置自增操作符(i++)

下面的代码来自Unreal Engine 4项目,其中有低效的代码被PVS-Studio诊断为:V803 Decreased performance. In case ‘itr’ is iterator it’s more effective to use prefix form of increment. Replace iterator++ with ++iterator(译者注:大意是说有性能下降的情况,建议把迭代器itr的后置++改成前置++)。

void FSlateNotificationManager::GetWindows(....) const
{
  for( auto Iter(NotificationLists.CreateConstIterator());
       Iter; Iter++ )
  {
    TSharedPtr<SNotificationList> NotificationList = *Iter;
    ....
  }
}

解释
如果你没有读这一章的标题,我觉得你可能很难发现上面代码中的问题。第一眼看上去,这部分代码正确无比,但其实并不完美。是的,我说的就是后置自增————“Iter++”。相比后置自增,你绝对应该使用一个前置的方式“++Iter”去代替“Iter++”。为什么要这么做?这么做的价值在哪里?我们接下去继续说。

高效的代码

for( auto Iter(NotificationLists.CreateConstIterator());
     Iter; ++Iter)

建议
一般来说,我们都知道前置自增和后置自增的区别(译者注:先自增再取值和先取值再自增的区别),我也希望其内在的结构区别(一般是底层的实现原理)对大家来说一样不是秘密(译者注:可惜大部分人不知道内在区别)。如果你曾经实现过这个自增操作符的重载,你一定就会知道其内在区别。如果没有,我就会在这里做一个简短的解释。(所有不清楚其内在区别的人都可以忽略这一段然后直接往后看,其中有操作符重载的代码示例)

前置自增操作符改变对象的状态,并且返回改变后的对象本身。没有临时的对象需求。前置自增操作符的实现一般如下:

MyOwnClass& operator++()
{
  ++meOwnField;
  return (*this);
}

后置自增操作符也改变了对象的状态,但返回的是前一个状态的对象,这就需要创建一个临时对象来实现。后置自增操作符的实现一般如下:

MyOwnClass operator++(int)
{
  MyOWnCLass tmp = *this;
  ++(*this);
  return tmp;
}

通过这些代码,你可以看到额外的代码用于创建临时对象了,在实际情况中又如何呢?

今天的编译器已经足够聪明到进行自动优化了,所以如果(临时对象)没有被使用就不会真的创建临时对象。这就是在Release版本中很难看到“it++”和“++it”区别的原因。

但在debug模式下调试程序时,情况就完全不一样了,这是性能上的不同会非常明显。

比如,在这篇文章中就有一些例子来评估在debug模式下使用前置和后置自增操作符的运行时间,我们可以看到使用后置自增操作符基本要多4倍的运行时间。

有人会说“那么在release版本中它们就一样吗?”,可以说他们说的对,但也说的不对。因为我们避免不了在单元测试和调试程序时使用debug版本从而花费更多的时间,但其我们并不希望浪费时间去等待。

总之我认为我们要回答这个问题————“我们应该在迭代器上使用前置自增操作符取代后置自增操作符吗?”,是的,我们应该这么做,这样你就会在debug版本中也能得到更好的速度。而且,一旦这个迭代器很重,那么获益就会更明显。

参考(阅读建议)

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值