将i ++优化为++ i以避免临时变量是否有意义?

Tho*_*son 18 c++ stl

有人告诉我,我可以写

for (iterator it = somecontainer.begin(); it != somecontainer.end(); ++it)
Run Code Online (Sandbox Code Playgroud)

代替

for (iterator it = somecontainer.begin(); it != somecontainer.end(); it++)
Run Code Online (Sandbox Code Playgroud)

...因为后者具有额外未使用的临时变量的成本.这种优化对现代编译器有用吗?编写代码时是否需要考虑这种优化?

Pot*_*ter 33

这是一个很好的习惯,因为迭代器可能是任意复杂的.对于vector::iteratorint索引,不,它不会有所作为.

编译器永远不会消除(删除)副本,因为复制省略只能消除中间临时值,而不是未使用的临时值.对于包括大多数迭代器的轻量级对象,编译器可以优化实现副本的代码.然而,它不能总是显而易见的.例如,增量的岗位istream_iterator<string>保证复制的最后一个string对象读取.在非引用计数的string实现上,将分配,复制和立即释放内存.该问题更可能适用于支持后增量的较重的非迭代器类.

当然没有缺点.它似乎已成为过去十年或二十年来的主流风格.

  • +1 - 不仅是迭代器,还有任何带有`operator ++`的类型. (7认同)

jal*_*alf 7

我通常不认为前缀++优化.这正是我默认编写的内容,因为它可能更快,编写起来同样容易,而且没有任何缺点.

但我怀疑是否值得返回并更改现有代码以使用前缀版本.


T.J*_*der 6

没有.(从文体上来说,我更喜欢它,因为我的母语是英语,主要是动词 - 先前 - 名词语言,因此"增量it"读取比" it增量" 更容易.但这是风格和主观.)

但是,除非您somecontainer在循环中更改内容,否则可以考虑将返回值somecontainer.end()转换为临时变量.你在那里做什么实际上会在每个循环上调用该函数.


sha*_*oth 6

是的,这在概念上是正确的.你关心它是否i++还是++i?不,你没有.哪一个更好?第二个更好,因为它可能更快.所以你选择第二个(预增量).

在典型情况下,发出的代码没有区别,但迭代器可以有任何实现.你无法控制它,你无法控制编译器是否会发出良好的代码.你可以控制的是你如何传达你的意图.你不需要这里的后增量.

  • @Billy ONeal:这将取决于迭代器在内部的实现方式以及编译器对它的看法.OP无法控制.他能控制的是他如何表达自己的意图. (2认同)