1

我正在尝试编写一个函数来通过递归打印数组。

我写了三个函数,但它们在原理上似乎是相同的。

void printArray0( int theArray[], int theSize, int theIndex = 0 )
{
    cout << theArray[theIndex] << ' ';
    if ( ++theIndex != theSize ) printArray0( theArray, theSize, theIndex );
    else cout << endl;
}

void printArray1( int theArray[], int theElementLeft )
{
    cout << *theArray << ' ';
    if ( theElementLeft != 1 ) printArray1( theArray+1, theElementLeft-1 );
    else cout << endl;
}

void printArray2( int theArray[], int theSize )
{
    static int myIndex = 0;
    cout << theArray[myIndex] << ' ';
    if ( ++myIndex != theSize ) printArray2( theArray, theSize );
    else cout << endl;
}

那么它们之间有显着差异吗?

如果有,哪个功能最快,哪个最安全?

我希望我能从别人的经验中学习:)

4

3 回答 3

4

第三个不等同于前两个,因为它使用一个静态变量来保持当前状态。这是一件坏事(想象一下从多个线程同时运行这个函数来看看为什么)。这甚至起作用的原因是,每次调用函数时都不会出现超过一次的递归调用。例如,试图在二叉树的递归遍历中保持静态状态会失败得相当惨。这就是为什么当前状态应该通过参数传递给递归函数,而不使用静态或成员上下文。

前两个版本之间应该没有性能差异,因为它们的时间将取决于数据的输出。

我会像这样更改第二个函数的签名

void printArray1( int *theArray, int theElementLeft )

因为您从不theArray用作数组,而仅用作指针。从技术上讲,这并不重要,因为数组无论如何都会“衰减”到指针,但我认为这会稍微提高可读性。

于 2013-04-10T14:21:57.810 回答
3

函数 0 和 1 是同样安全的1

函数 2 在多线程环境中是不安全的,因为它使用了静态变量。此外,对该函数的连续调用将从最后一次调用“停止”的地方开始,因为myIndex在任何地方都不会重新初始化为零。


1我个人更喜欢函数 1 的风格而不是函数 0。函数 0 在使用预增量 ( if ( ++theIndex != theSize )) 方面很聪明,在我看来,这种聪明会妨碍未来的维护。我建议您避免出现有副作用的情况。

于 2013-04-10T14:21:55.940 回答
1

它们都没有多大意义,没有理由有人会为此使用递归。第一个版本可能是最不坏的,因为它最容易阅读。

的版本static是最危险的,因为它不是线程安全的。并且使用 static 使整个递归(甚至更多)毫无意义。

通常,递归有意义的情况很少,这不是其中之一。所有三个版本都是危险的,因为如果参数不正确,不能保证递归会停止。所有三个版本都将比普通循环消耗更多的 RAM 内存,并且它们的执行速度会更慢,同时也会使您的程序的可读性大大降低。您的程序将容易受到堆栈溢出的影响。

编译器通常不会那么有效地优化递归。他们是否这样做可能取决于您是否使用“尾递归”。

作为旁注,您的编码和缩进样式不可读且不安全。在 if/else 之后的每一行都使用一个新行,并始终{}用于每个 if/else 语句。

于 2013-04-10T14:33:34.370 回答