为什么这个递归函数会破坏?

时间:2015-11-09 18:23:38

标签: c++ pointers

我正在尝试创建一个函数,该函数将获取指针的地址并将值(它指向的值)减少为1。一旦它等于1,它将返回1.当我这样做时,它打印出来:

10 
9
8
7
6
5
4
3
2
1
32767

代码:

#include <iostream>

using namespace std;

int downToOne(int * & x)
{
  if(*x == 1)
    return 1;

  else
  {
    (*x)--;
    cout<<*x<<endl;
    downToOne(x);   
  }

}

int main() 
{

  int *Ptr = new int(10);
  cout<<*Ptr<<endl;

  cout<<downToOne(Ptr)<<endl;
  return 0;
}

为什么打印出32767

6 个答案:

答案 0 :(得分:4)

因为这是第一次调用downToOne的(未定义的)返回值。主例程是打印第一次调用downToOne返回的值。递归调用发生在downToOne中,当您流经该路径时,downToOne不返回值。如果你把&#34;返回9999;&#34;在downToOne中递归调用之后,你会看到它打印9999.由于没有明确的返回,你可能会得到函数返回的堆栈中的任何值。

答案 1 :(得分:1)

您的程序受到未定义的行为,因为函数downToOnereturn分支中没有else语句。

简化为:

int downToOne(int* x) // You don't need a reference to the pointer.
{
   if(*x == 1)
      return 1;

   (*x)--;
   cout<<*x<<endl;
   return downToOne(x);   
}

如果*x小于1,该函数将导致无限递归。为了防止出现这种问题,最好使用:

int downToOne(int* x)
{
   if(*x <= 1)  // Prevents infinite recursion
      return 1;

   (*x)--;
   cout<<*x<<endl;
   return downToOne(x);   
}

答案 2 :(得分:1)

正如我的评论所述,如果您开始使用2而不是10,那么这个问题应该是显而易见的,或者至少是非常简单的调试和诊断

通常,如果存在递归问题,请从最简单的情况开始。如果最简单的情况不起作用,请不要尝试对递归函数进行压力测试。

让我们看看如果输入更改为2而不是10会发生什么:

int downToOne(int * & x)
{
  if(*x == 1)  // first time, *x is 2, so the return is not executed.
    return 1;  // second time we return 1.

  else
  {
    (*x)--;   // *x now becomes 1
    cout<<*x<<endl;  // a "1" is printed
    downToOne(x);    // we call again
  }
}

让我们看看您的main功能:

int main() 
{
  int *Ptr = new int(2);
  cout << *Ptr << endl;  // prints a "2"
  cout << downToOne(Ptr) << endl;  // prints a "1" inside of the function, and prints the return value, which is undefined
  return 0;
}

因此,即使您没有意识到未定义的行为,您的main函数也无法只打印2个数字。打印出3个数字。

  1. 打印初始“2”
  2. downToOne
  3. 内打印“1”
  4. downToOne的返回值打印在main
  5. 鉴于这种情况,那么有两个问题。第一个是未定义的值(其他人已经回答),第二个是你打印的次数太多了。

答案 3 :(得分:0)

原因是在else分支中它不会返回任何内容,但是您正在使用该分支的返回值作为上一个cout语句。所以它输出一个随机值。如果你将一个return语句添加到else分支中,那么从那里返回的任何内容都将在当前输出中输出而不是32767。

答案 4 :(得分:-1)

它应该生成的输出是

10 9 8 7 6 五 4 3 2 1 1

当* x为2时,它进入else块,将* x减1,然后打印出来。然后堆栈上的第一个调用(从main())打印另一个1.

您确定要运行相同的代码吗?

答案 5 :(得分:-3)

这种方式很好....

{
    int* ptr = new int(10);
    cout << "ptr = " << *ptr << "\n\n";

    int downToOne(int*); //THIS is the correct form

    cout << downToOne(ptr) << "\n";

    return 0;
}


int downToOne(int* x)
{
    if(*x == 1)
        return 1;

    else
    {
        cout << *x << endl;
        (*x)--;
        downToOne(x);
    }
}

ptr = 10

10
9
8
7
6
5
4
3
2
1
Press <RETURN> to close this window...

编辑2015-11-10_15:15

你去了,这个版本也有效,并且有一个return表达式。

int downToOne(int* x)
{
//    if(*x == 1) //comment out
//        return 1; //comment out
//    else //comment out
//    { //comment out

    if (*x != 1) //add this
    { //add this
        cout<<*x<<endl;
        (*x)--;
        downToOne(x);
    } //add this

//    } //comment out

    return *x; //add this
}