为什么 for 循环中的 "++i" 和 "i++" 之间有什么区别?
Why is there any difference between "++i" and "i++" in a for loop?
在我看来
for(int i = 0; i < 2; i++)
和
for(int i = 0; i < 2; ++i)
不应该做同样的事情。对于第二个例子,我认为从循环开始,i应该等于1更符合逻辑。
在一些处理器上,如PDP-11、VAX-11和68K,有些指令的模式相当于*ptr++
和*--ptr
。根据编写代码的确切方式,编译器可能会或可能不容易利用这些指令-因此,在循环中使用*++ptr
或*ptr++
的"正确"变体[更好的取决于实际循环中的用法]可以在这些特定情况下产生相当大的性能差异。然而,对于ARM和x86(我认为,还有PowerPC和MIPS,因此几乎涵盖了所有现代处理器),这种类型的结构无论如何都不是指令集的一部分,而且现在的编译器比10年或20年前要聪明得多。
任何合理的编译器都会对基本类型做同样的事情,i++
或++i
不是问题。
如果我们有一个"复杂"的类型,例如具有operator++(int)
和opterator++()
的结构或类,可能会有很小的区别[或者在极端情况下,有很大的区别],因为对象必须被复制。假设我们有一个bigmath
类,我们的i
是一个1000位的长值。现在我们必须在增量的中间做一个(n个额外的)1000位数的拷贝。如果编译器能够"理解"正在发生的事情,它可能会省略该副本,但不能保证会发生。
在我看来,他们应该做完全相同的事情。都有增加i
的效果。
i++
给出增量之前的值,++i
给出增量之后的值。但是在这种情况下,该值将被丢弃,并且表达式仅对其副作用进行评估;因此,代码的效果没有区别。
在某些情况下(如果i
不是int
,而是某些用户定义的类型,其重载操作符过于复杂,编译器无法理解),++i
可以更有效。这是因为i++
需要复制以返回旧值,而++i
只需要返回对新值的引用。当然,一个足够疯狂的用户定义类型可能会使两个重载做完全不同的事情。但是对于简单类型,也没有区别。
尽管考虑返回值时++i
和i++
具有不同的功能,但在几乎所有情况下,编译器都会将i++
优化为++i
for循环。
如果你不知道++i
递增然后返回新的i
的值,而i++
递增然后返回旧的i
的值。前者在技术上更有效,因为您不需要存储中间值,但总体而言,它们实际上没有太大区别,除非您试图进行代码高尔夫并使用返回值。
在您的示例中:no差异。如果该类型是用户定义的类型,则可能存在很大差异。
至于哪一个更合乎逻辑当然是一个有争议的问题。建议你遵循团队的风格或者任何适合你的工作。在你的上下文中,是一样的。++i
和i++
的区别在于操作顺序。如果你是一个疯狂邪恶的C程序员,你可能会写这样的代码:
int i = 3;
if( ++i++ == 4 )
printf( "%dn", i);
将输出
5
因为在if测试中我将是4,但在测试后立即是5。
在我的第一学期,我的讲师煞费苦心地向全班解释这个问题。根据我的回忆,我很确定它的来龙去脉主要与'返回'值有关,例如:
++i将增加i的值,并返回增加后的值,直到操作完成。然而,尽管i++也会增加该值,但如果在操作期间调用该变量,它将返回未增加的值。
如果你有这个:
a = 1;
b = ++a;
c = 10;
d = c++;
则值为
a = 2
b = 2
c = 11
d = 10
(d是这样的,因为c返回的是'post' ++'s而不是通常的'pre' ++'s)。
在循环中完全没有区别,因为自增值在循环语句中,而不是在它后面的操作中。唯一能起作用的是
for(i = 0; i<5;)
printf("%d ",++i);
,其中0的值不会被打印,而5的值会被打印,因为它在打印过程中增加了。
清晰如泥,是吗??不要问我为什么这被编程成C!在我看来,这似乎是多余的,一些很少弹出的东西,任何需要它的程序都可以通过额外的一行代码来改变不同变量的值来解决问题!
在你的例子中是一样的,因为你的表达式的返回值没有被使用。
- Mix_Init和Mix_OpenAudio SDL之间的区别是什么
- 我是C++编程的新手,这些代码之间有什么区别,我应该使用哪一个
- 在两台机器之间进行时间戳的最佳c++chrono函数是什么
- 这 4 个 lambda 表达式之间有什么区别?
- 空指针常量 (nullptr)、空指针值和空成员指针值之间有什么区别?
- 不同的类或结构初始化方法之间的性能差异是什么?
- "constinit"和"constexpr"之间的真正区别是什么?
- 在什么条件下使用 std::memcpy 在对象之间复制是安全的?
- 移动语义和深层/浅层复制之间有什么关系?
- 这两种C++语法之间有什么区别?
- #include < conio.h> 和 getch() 方法之间的关系是什么?
- ((int) a) 和 (int(a)) 之间的区别是什么?
- ( var > x) 和 ( x < var)之间有什么区别吗?
- 在 C 和 C++ 中作为函数参数,int **a 和 int a[][] 之间有什么确切的区别
- 返回引用实例和非引用实例(return mystr & vs mystr)之间的区别是什么?
- 超市管理系统的类别之间应该是什么关系?
- 指针和程序性能之间有什么关系吗?
- 这些初始化之间有什么区别?
- 空字符和"\0"之间有什么区别?
- 无符号长整型和无符号 int 之间有什么区别,这 2 种类型应该如何在 c# 中封送?