我不明白后缀和前缀增量或减量的概念。谁能给出更好的解释?
到目前为止,所有四个答案都是不正确的,因为它们声明了特定的事件顺序。
相信“都市传奇”已经导致许多新手(和专业人士)误入歧途,即表达式中关于未定义行为的无穷无尽的问题。
所以。
对于内置的C ++前缀运算符,
++x
增加x
并产生表达结果x
作为左值,而
x++
增加x
并生成x
的原始值作为表达式结果。
特别是,对于x++
,没有时间排序暗示增加和生成x
的原始值。编译器可以自由地发出产生x
原始值的机器代码,例如:它可能存在于某个寄存器中,并将增量延迟到表达式结束(下一个序列点)。
不正确地相信增量的人必须首先出现,并且他们很多,通常得出结论,当某些表达式实际上具有未定义的行为时,它们必须具有明确定义的效果。
前增量在增量值++
之前,例如:
(++v) or 1 + v
后增量是增加值++
例如:
(rmv++) or rmv + 1
程序:
int rmv = 10, vivek = 10;
cout << "rmv++ = " << rmv++ << endl; // the value is 10
cout << "++vivek = " << ++vivek; // the value is 11
您还应该意识到后递增/递减运算符的行为在C / C ++和Java中是不同的。
特定
int a=1;
在C / C ++中的表达方式
a++ + a++ + a++
评估为3,而在Java中,它评估为6.猜猜为什么......
这个例子更令人困惑:
cout << a++ + a++ + a++ << "<->" << a++ + a++ ;
打印9 < - > 2 !!这是因为上面的表达式相当于:
operator<<(
operator<<(
operator<<( cout, a++ + a++ ),
"<->"
),
a++ + a++ + a++
)
int i, x;
i = 2;
x = ++i;
// now i = 3, x = 3
i = 2;
x = i++;
// now i = 3, x = 2
'Post'表示之后 - 也就是说,在读取变量之后完成增量。 'Pre'表示之前 - 所以变量值首先递增,然后在表达式中使用。
没有人回答这个问题:为什么这个概念令人困惑?
作为一门本科计算机科学专业,由于我阅读代码的方式,我花了一些时间来理解这一点。
以下是不正确的!
x = y ++
X等于y post增量。这在逻辑上似乎意味着X在增量操作完成后等于Y的值。发表后的意思。
要么
x = ++ y X等于y预增量。这在逻辑上似乎意味着X在增量操作完成之前等于Y的值。之前的意思。
它的工作方式实际上恰恰相反。这个概念令人困惑,因为这种语言具有误导性。在这种情况下,我们不能使用这些词来定义行为。 实际读取x = ++ y,因为X等于增量后的Y值。 实际上读取x = y ++,因为X等于增量前的Y值。
关于英语的语义,前后词是倒退的。它们只表示++与Y相关的位置。仅此而已。
就个人而言,如果我有选择,我会改变++ y和y ++的含义。这只是我必须学习的成语的一个例子。
如果有一种解决这种疯狂的方法,我想简单地说一下。
谢谢阅读。
后缀增量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
在增量后计算为x
的值。
很容易认为表达式++x
因此等同于assignmnet (x=x+1)
。然而,这并非如此,因为增量是一种在不同环境中可能意味着不同事物的操作。在简单的原始整数的情况下,++x
确实可以替代(x=x+1)
。但是在类类型的情况下,例如链表的迭代器,迭代器的前缀增量绝对不意味着“向对象添加一个”。
这很简单。两者都会增加变量的值。以下两行相同:
x++;
++x;
不同之处在于,如果您使用的是增量变量的值:
x = y++;
x = ++y;
这里,两条线都将y的值递增1。但是,第一个在增量之前将y的值赋给x,第二个在增量之后将y的值赋给x。
因此,当增量也被用作表达式时,只有区别。返回值后的后增量递增。之前的增量前递增。
int 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
后增量意味着值i
在分配给k
后递增。但是,预增量意味着值j在分配给l
之前递增。
这同样适用于减量。
后增量(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。
由于我们现在有内联的javascript片段,我不妨添加pre和pos增量的交互式示例。它不是C ++,但概念保持不变。
let A = 1;
let B = 1;
console.log('A++ === 2', A++ === 2);
console.log('++B === 2', ++B === 2);
从C99标准(C ++应该是相同的,除非奇怪的重载)
6.5.2.4后缀增量和减量运算符
约束
1后缀增量或减量运算符的操作数应具有限定或不合格的实数或指针类型,并且应为可修改的左值。
语义
2 postfix ++运算符的结果是操作数的值。获得结果后,操作数的值递增。 (即,将相应类型的值1添加到其中。)有关约束,类型和转换以及操作对指针的影响的信息,请参阅加法运算符和复合赋值的讨论。更新操作数的存储值的副作用应发生在前一个和下一个序列点之间。
3后缀 - 运算符类似于后缀++运算符,除了操作数的值递减(即,从中减去相应类型的值1)。
6.5.3.1前缀增量和减量运算符
约束
1前缀增量或减量运算符的操作数应具有合格或不合格的实数或指针类型,并且应为可修改的左值。
语义
2前缀++运算符的操作数的值递增。结果是增量后操作数的新值。表达式++ E等价于(E + = 1)。有关约束,类型,副作用和转换以及操作对指针的影响的信息,请参阅加法运算符和复合赋值的讨论。
3前缀 - 运算符类似于前缀++运算符,除了操作数的值递减。