为什么 ++i 比 i++ 更有效率?

4
根据Google C++语言风格指南,“当返回值被忽略时,'前缀'形式(++i)不会比'后缀'形式(i++)效率低,并且通常更加高效。”该指南进一步解释了其中的原理,但我并不完全理解。有什么想法吗?也许有人可以提供一个这个概念的例子?

1
这并不是必然的:https://dev59.com/uXVD5IYBdhLWcg3wTJvF - maditya
1
@maditya,那个问题是关于C语言的,不是C++。答案是不同的。 - Pubby
是的,发布后才注意到这一点,很抱歉。如果我删除评论会不会让人感到困惑? - maditya
我现在有点混乱,但自从操作符重载以来,你永远无法确定哪一个(*crements)会更快(至少在C++中)。 - Kupto
删除了C标签,因为按照问题描述,与C无关。 - R.. GitHub STOP HELPING ICE
显示剩余2条评论
6个回答

15

i++会使i的值加一并返回i的初始值。

int i = 1;
i++; // == 1 but i == 2

但是++i会返回实际递增的值:

int i = 1;
++i; // == 2 and i == 2 too, so no need for a temporary variable
在第一种情况下,编译器必须创建一个临时变量(在使用时),以返回1而不是2(当然,如果它不是常量而是动态值,例如从调用中返回)。
在第二种情况下,它不必这样做。因此第二种情况保证至少与第一种情况一样有效。
通常,编译器将能够将第一种情况优化为第二种情况,但有时可能无法这样做。
总之,我们谈论的是高度微不足道的影响。
但是对于像迭代器之类的更复杂对象,如果迭代数百万次,拥有临时状态可能会相当慢。
经验法则
除非您明确需要后缀语义,否则请使用前缀版本。

2

摘自:

http://www.parashift.com/c++-faq/increment-pre-post-speed.html

++i有时比i++更快,而且绝不会更慢。

对于诸如int之类的内部类型,这不重要:++i和i++的速度相同。但是对于类类型(例如迭代器)而言,++i很可能比i++更快,因为后者可能会复制此对象。

如果存在i ++的开销,则它可能根本不会产生任何实际差异,除非您的应用程序受到CPU限制。例如,如果您的应用程序大部分时间都在等待某人点击鼠标、进行磁盘I/O、网络I/O或数据库查询,则浪费一些CPU周期不会影响性能。但是,敲击++i与i++一样简单,因此,除非您实际上需要i的旧值,否则为什么不使用前者呢。

因此,如果将i++作为语句而不是作为较大表达式的一部分编写,为什么不直接编写++i呢?你永远不会失去任何东西,有时候你还可以获得一些东西。老一代的C程序员习惯于编写i++而不是++i。例如,他们会说:

for (i = 0; i < 10; i++) .... 

由于这里使用的是i++作为语句,而不是作为较大表达式的一部分,因此您可能想使用++i。出于对称性的考虑,即使在不提高速度的情况下,例如对于内在类型和返回void的后缀运算符的类类型,我个人也主张采用这种风格。


0

i++ - 在使用 i 后增加值 ++i - 立即增加值。

由于 ++i 要求立即增加 i,因此可能会有性能差异。i++ 表示在增加之前可能需要使用 i。该值可能会在增加之前存储在某个地方。


0

增量(或减量)运算符涉及两个操作:增量和将两个值(旧值或新值)中的一个作为表达式的结果。区别在于要选择哪一个。

如果您采用前缀形式,您首先会增加然后取值,即新值。

如果您采用后缀形式,您将获取旧值,保留它,增加它,将新值放入旧位置并返回旧值。这听起来更复杂 - 而且确实如此。

但是,如果忽略表达式的返回值,则无论您使用内置类型还是对象,都不应该有任何区别。


0

对于迭代器和其他模板类型,请使用前置递增。


1
这个问题是关于“为什么会这样”的。 - glglgl
这是因为后增量(或减量)需要复制 i 的副本,这就是表达式的值。如果 i 是迭代器或其他非标量类型,则复制 i 可能很昂贵。 - llSpectrell

0

这是因为当您进行后置递增时,您必须:

  1. 更改该值并同时
  2. 将旧值分配给其他变量。

简单来说,您必须保留该变量的两个副本,并且复制和删除是需要额外时间的原因...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接