++什么时候不会产生与+1相同的结果?
以下两个Ccode代码段产生不同的结果(假定在递归调用之前和之后都使用变量级别)。为什么?
public DoStuff(int level) { // ... DoStuff(level++); // ... }
,
public DoStuff(int level) { // ... DoStuff(level+1); // ... }
阅读下面的一些回答后,我认为值得发布有关level ++,++ level和level + 1的堆栈跟踪记录,以突出说明如何解决此问题。
我为这篇文章简化了它们。递归调用序列以DoStuff(1)开始。
//级别++
DoStuff(int level = 1) DoStuff(int level = 2) DoStuff(int level = 2) DoStuff(int level = 2)
// ++级
DoStuff(int level = 4) DoStuff(int level = 4) DoStuff(int level = 3) DoStuff(int level = 2)
// +1级
DoStuff(int level = 4) DoStuff(int level = 3) DoStuff(int level = 2) DoStuff(int level = 1)
解决方案
level ++会将级别传递给DoStuff,然后递增级别以在其余函数中使用。这可能是一个非常讨厌的错误,因为递归将永远不会结束(根据所示,DoStuff始终会传递相同的值)。也许++ level是相反的意思,因为这与level ++相反(递增级别,并将递增的值传递到DoStuff中)?
级别+1将级别+1传递到DoStuff中,而其余部分的级别保持不变。
首先是在水平中使用该值,然后将其递增。
后者使用level + 1作为传递变量。
第一个代码段使用后操作增量运算符,因此调用以DoStuff(level);进行。如果要在此处使用增量运算符,请使用DoStuff(++ level);。
" level ++"返回" level"的当前值,然后递增" level"。
" level + 1"根本不改变" level",但是以"(level + 1)"的值调用" DoStuff"。
因为第一个示例实际上等效于:
public DoStuff(int level) { // ... int temp = level; level = level + 1; DoStuff(temp); // ... }
注意,我们也可以编写++ level。那将等同于:
public DoStuff(int level) { // ... level = level + 1; DoStuff(level); // ... }
我认为最好不要过度使用++和-operators;它很快就会引起混乱和/或者不确定实际发生的事情,并且现代的C ++编译器无论如何都不会使用这些运算符生成更有效的代码。
级别+1将任何级别+1发送给该函数。
level ++将级别发送给函数,然后将其递增。
我们可以进行++级的操作,这很可能会为我们提供所需的结果。
第一个示例使用'index'的值,增加值并更新'index'。
第二个示例使用'index'的值加1,但不更改'index'的内容。
因此,根据我们想要在这里做什么,商店中可能会有一些惊喜!
就我的经验而言,参数表达式首先被求值,并获得level的值。
变量本身在函数被调用之前就增加了,因为编译器不在乎我们是否使用表达式作为参数……否则,它所知道的是它应该增加值并获得旧值作为结果。表达。
但是在我看来,这样的代码确实很草率,因为试图变得聪明,它使我们必须三思而后行。
level ++的返回值将是level,因此将level传递给DoStuff。这可能是一个非常讨厌的错误,因为递归将永远不会结束(从所示的DoStuff
总是以相同的值传递)。也许是" ++ level"或者" level + 1"的意思呢?
" level + 1"将" level + 1"传递到" DoStuff"中,而在其余功能中," level"保持不变。
后增量运算符(variable ++)与该函数完全等效
int post_increment(ref int value) { int temp = value; value = value + 1 return temp; }
而预增量运算符(++变量)恰好等于该函数
int pre_increment(ref int value) { value = value + 1; return value; }
因此,如果将内联运算符扩展为代码,则这些运算符等效于:
DoStuff(a + 1) int temp = a + 1; DoStuff(temp);
DoStuff(++a) a = a + 1; DoStuff(a);
DoStuff(a++); int temp = a; a = a + 1; DoStuff(temp);
重要的是要注意,后增量不等于:
DoStuff(a); a = a + 1;
此外,作为一种风格,除非打算使用递增的值(规则的特定版本,"除非我们打算使用该值,否则不要为变量赋值"),否则不应递增值。 )。如果不再使用值" i + 1",则首选用法应该是" DoStuff(i + 1)",而不是" DoStuff(++ i)"。
为了阐明所有其他答复:
+++++++++++++++++++++++
DoStuff(a++);
等效于:
DoStuff(a); a = a + 1;
+++++++++++++++++++++
DoStuff(++a);
等效于:
a = a + 1; DoStuff(a);
+++++++++++++++++++++++
DoStuff(a + 1);
等效于:
b = a + 1; DoStuff(b);
+++++++++++++++++++++++
public DoStuff(int level) { // DoStuff(level); DoStuff(level++); // level = level + 1; // here, level's value is 1 greater than when it came in }
它实际上增加了level的值。
public DoStuff(int level) { // int iTmp = level + 1; // DoStuff(iTmp); DoStuff(level+1); // here, level's value hasn't changed }
实际上不会增加level的值。
在函数调用之前这不是一个大问题,但是在函数调用之后,值将有所不同。
虽然很诱人地将其重写为:
DoStuff(++level);
我个人认为,这比在方法调用之前增加变量的可读性差。正如上面的几个答案所指出的,以下内容将更加清楚:
level++; DoStuff(level);
当我们使用允许运算符重载的语言时,已经定义了'+ <integer>'来执行除前缀'++'之外的其他操作。
再说一次,我只在学校项目中看到过这样的可憎之处*,如果我们在野外遇到这种情况,我们可能有一个很好的,有据可查的理由。
[*一堆整数,如果我没记错的话。按下并弹出" ++"和"-",而" +"和"-"执行常规算术]
在level ++中,我们正在使用后缀运算符。使用该变量后,该运算符将起作用。也就是说,将其放入调用函数的堆栈后,它会递增。另一方面,级别+ 1是简单的数学表达式,并且对其求值并将结果传递给被调用的函数。
如果要先递增变量,然后将其传递给被调用的函数,则可以使用前缀运算符:++ level