是否有一些程序员++i
在正常的 for 循环中编写而不是编写的原因i++
?
9 回答
++i
由于其语义,效率稍高:
++i; // Fetch i, increment it, and return it
i++; // Fetch i, copy it, increment i, return copy
对于类似 int 的索引,效率增益是最小的(如果有的话)。对于迭代器和其他重量较重的对象,避免该副本可能是一个真正的胜利(特别是如果循环体不包含太多工作)。
例如,考虑以下循环,使用理论 BigInteger 类提供任意精度整数(以及某种类似矢量的内部结构):
std::vector<BigInteger> vec;
for (BigInteger i = 0; i < 99999999L; i++) {
vec.push_back(i);
}
i++ 操作包括复制构造(即操作符 new,逐位复制)和破坏(操作符删除),用于一个循环,除了本质上再制作一个索引对象的副本之外,它不会做任何事情。本质上,您只需使用前缀就足够的后缀增量,就可以将要完成的工作加倍(并且很可能会增加内存碎片)。
对于整数,前增量和后增量之间没有区别。
如果i
是一个非平凡类的对象,那么++i
通常是首选的,因为该对象被修改然后评估,而i++
在评估之后修改,因此需要制作副本。
++i
是一个预增量;i++
是后增量。
后增量的缺点是它会产生额外的价值。它在修改时返回旧值的副本i
。因此,您应该尽可能避免它。
对于整数,这是首选。
如果循环变量是一个类/对象,它可以产生影响(只有分析可以告诉你它是否是一个显着的差异),因为后增量版本要求你创建一个被丢弃的对象的副本。
如果创建该副本是一项昂贵的操作,那么您每次通过循环都要支付一次费用,完全没有理由。
如果您养成始终使用++i
in for 循环的习惯,则无需停下来思考在这种特殊情况下所做的事情是否有意义。你总是这样。
没有哪个编译器值得在盐中发挥作用
for(int i=0; i<10; i++)
和
for(int i=0;i<10;++i)
++i 和 i++ 具有相同的成本。唯一不同的是 ++i 的返回值是 i+1 而 i++ 的返回值是 i。
所以对于那些喜欢 ++i 的人来说,可能没有有效的理由,只是个人喜好。
编辑:这对班级来说是错误的,正如在其他所有帖子中所说的那样。如果 i 是一个类, i++ 将生成一个副本。
这是有原因的:性能。i++ 生成一个副本,如果您立即丢弃它,那是一种浪费。当然,如果是原语,编译器可以优化掉这个副本i
,但如果不是,则不能。看到这个问题。
正如其他人已经指出的那样,对于用户定义的类型,预增量通常比后增量更快。要了解为什么会这样,请查看实现这两个运算符的典型代码模式:
Foo& operator++()
{
some_member.increase();
return *this;
}
Foo operator++(int dummy_parameter_indicating_postfix)
{
Foo copy(*this);
++(*this);
return copy;
}
如您所见,前缀版本只是简单地修改对象并通过引用返回它。
另一方面,后缀版本必须在执行实际增量之前进行复制,然后将该副本按值复制回调用者。从源代码中可以明显看出后缀版本必须做更多的工作,因为它包含对前缀版本的调用:++(*this);
对于内置类型,只要您丢弃该值,即只要您不嵌入++i
或i++
在更大的表达式(如a = ++i
or )中,它就没有任何区别b = i++
。
当您使用后缀时,它会在内存中实例化更多对象。有人说在for循环中使用后缀操作符比较好
个人喜好。
通常。有时这很重要,但不要在这里看起来像个混蛋,但如果你不得不问,它可能不会。