我不理解后缀和前缀的自增或自减概念。有没有人能给出更好的解释呢?
我不理解后缀和前缀的自增或自减概念。有没有人能给出更好的解释呢?
到目前为止,所有四个答案都不正确,因为它们断言了一种特定的事件顺序。
相信“城市传说”误导了许多初学者(和专业人士),即关于表达式中未定义行为的无尽问题。
所以。
对于内置的 C++ 前缀运算符,
++x
增加x
的值,并将其作为左值返回
x++
x++
操作会使 x
的值加 1,并将加 1 前的原始值作为表达式的结果返回。
特别地,x++
并不意味着增量和返回原始值的时间顺序是确定的。编译器可以生成一些机器码,以产生 x
的原始值(例如可能存在于某个寄存器中),并延迟增量直到表达式结束(下一个序列点)。
一些错误地认为增量必须先发生的人往往得出某些表达式必须具有明确定义效果的结论,但实际上这些表达式具有未定义行为。
&&
运算符引入了一个序列点(C++03 §1.9/18)。在C++11标准下,内置的&&
运算符中左侧操作数表达式先于右侧操作数表达式被计算(C++11 §5.14/2)。这意味着如果进行调用,它将使用i
的值6。 - Cheers and hth. - Alfx++ + y(x)
?或者使用 ++x
的等效表达式呢?如果我现在有 c++ 环境的话,我可能会尝试一下,但不幸的是我没有... - AJMansfield&&
和||
这两个操作符在提供短路求值(因此也有序列点)方面是独特的。三元选择操作符也有点类似,因为它保证不选中的选择不被评估。但对于算术操作符,当您在同一表达式中修改并使用变量时,就会发生未定义行为。我认为,但不确定,所有其他操作符也是如此。无论如何,这是最好的假设,并且编写依赖于一些微妙的特殊情况的代码并不好,因为很少有程序员知道这些细节。;-) - Cheers and hth. - Alfint i, x;
i = 2;
x = ++i;
// now i = 3, x = 3
i = 2;
x = i++;
// now i = 3, x = 2
'Post' 的意思是后缀 - 即,在读取变量之后进行递增。'Pre' 的意思是前缀 - 因此,变量值先被递增,然后再用于表达式。
后缀递增运算符x++
和前缀递增运算符++x
之间的区别在于它们如何评估其操作数。后缀递增运算符在概念上将操作数复制到内存中,递增原始操作数,最后生成副本的值。我认为通过代码实现运算符是最好的说明方式:
int operator ++ (int& n) // postfix increment
{
int tmp = n;
n = n + 1;
return tmp;
}
上述代码无法编译,因为你不能重新定义原始数据类型的运算符。编译器也无法判断我们定义的是一个后缀运算符而不是前缀运算符,但假设这是正确且合法的C++代码。你可以看到后缀运算符确实作用于它的操作数,但它返回的是自增之前的旧值。因此表达式x++
的结果是自增之前的值。然而,x
的确被自增了。
前缀自增也将操作数自增,但它返回的是自增之后的操作数值:
int& operator ++ (int& n)
{
n = n + 1;
return n;
}
这意味着表达式++x
的值是在加1之后 返回的x
值。
很容易认为表达式++x
等同于赋值(x=x+1)
,但实际上不完全是这样的,因为增量是一种在不同上下文中可能具有不同含义的操作。对于一个简单的原始整数,确实++x
可以替换(x=x+1)
。但对于类类型,例如链表的迭代器,迭代器的前缀增量绝对不意味着"将对象加1"。
x = y++
X 等于 y 后置自增。从逻辑上看,这似乎意味着 X 等于 Y 在自增操作完成之后的值。"Post" 意味着 "之后"。
或者
x = ++y
X 等于 y 的前置自增。从逻辑上看,这似乎意味着 X 等于在自增操作之前的值。"Pre" 意味着 "之前"。
它实际上的工作方式是相反的。这个概念很难理解是因为语言具有误导性。在这种情况下,我们不能使用单词来定义行为。
x=++y 实际上被解读为 X 等于自增之后的 Y 值。
x=y++ 实际上解读为 X 等于自增之前的 Y 值。
单词 "pre" 和 "post" 在语义上与英语相反。它们只表示++在 Y 的相对位置,没有其他的含义。
就我个人而言,如果可以选择,我会交换 ++y 和 y++ 的含义。这只是一个我必须学习的成语的例子。
如果有一种方法来理解这种疯狂的行为,我想以简单的方式了解。
谢谢阅读。
++y
是前缀自增,因为 ++
用作前缀,y++
是后缀自增,因为 ++
用作后缀(或“后缀”)。这与英语语言并不矛盾。 - Pharap很简单。两者都会增加变量的值。以下两行代码是等价的:
x++;
++x;
区别在于你是否使用变量的值进行递增:
x = y++;
x = ++y;
这里,两行代码都将y的值加一。然而,第一行将增量之前的y的值分配给x,而第二行将增量后的y的值分配给x。
因此,只有在增量也被用作表达式时才有区别。后置增量在返回值后增加。前置增量在之前增加。
x++;
和 ++x;
这两个语句的效果是相同的。是的,你调用了不同的函数,但它们应该做相同的事情。这就是我试图表达的意思。 - James McNellisint i = 1;
int j = 1;
int k = i++; // post increment
int l = ++j; // pre increment
std::cout << k; // prints 1
std::cout << l; // prints 2
后增量意味着在将值赋给k
之后,值i
会被增加。然而,前增量意味着在将值赋给l
之前,值j
会被增加。
递减也是同样的道理。
后自增:
int x, y, z;
x = 1;
y = x++; //this means: y is assigned the x value first, then increase the value of x by 1. Thus y is 1;
z = x; //the value of x in this line and the rest is 2 because it was increased by 1 in the above line. Thus z is 2.
前缀递增:
int x, y, z;
x = 1;
y = ++x; //this means: increase the value of x by 1 first, then assign the value of x to y. The value of x in this line and the rest is 2. Thus y is 2.
z = x; //the value of x in this line is 2 as stated above. Thus z is 2.
这里已经有很好的答案了,但通常似乎缺乏一些普遍的清晰度,只是简单地记住它们的工作方式。我想这是因为语义上解决命名并不完全直观。例如,您可能知道“pre-”表示“之前”。但是,pre-increment ++i 是否返回增量之前的 i 的值,还是在返回值之前增加 i?
我发现从左到右视觉上跟随表达式要容易得多:
++ i
-------------------------------------------------->
Increment i Then supply the value of i
i ++
-------------------------------------------------->
Supply the value of i Then increment i
现在我们有内联JavaScript代码片段,我可以添加一个关于前置和后置增量的交互式示例。虽然不是C++,但概念相同。
let A = 1;
let B = 1;
console.log('A++ === 2', A++ === 2);
console.log('++B === 2', ++B === 2);
后置递增(a++)
如果 int b = a++,那么这意味着
int b = a;
a = a+1;
这里我们将值加1。在增量进行之前,返回该值,
例如 a = 1; b = a++;
那么 b=1,a=2
预增量 (++a)
如果 int b = ++a; 那么这意味着
a=a+1;
int b=a ;
前缀自增:这将在主值上加1。增量完成后,该值将被返回。例如a = 1; b = ++a; 那么b = 2,a = 2。