StackTop 函数的这两种不同实现之间有什么区别?

What is the difference between these two different implementations of StackTop function?

我正在学习一门关于数据结构的课程,目前我被堆栈中的东西困住了。在 StackTop 函数的实现中(它使副本或“returns 在某种意义上 ” 成为堆栈中的顶部元素而不影响堆栈。)下面代码是它的实现,很清楚,

void StackTop(StackEntry *pe, Stack *ps){
    *pe=ps->entry[ps->top-1];
}

但是只要我们想给用户栈顶元素的值,我们就不能把函数做成这样吗?如果是这样,那么这两种实现之间有什么区别?

StackEntry StackTop(Stack *ps){
    return ps->entry[ps->top-1];
}

请记住 StackEntry 是用户定义的数据类型。

两者都可以。主要区别在于完成的份数。

在第一种情况下,结果值通过指针取消引用直接写入目标变量。在第二种情况下,值(在大多数实现中)被放入堆栈,然后复制到接收 return 值的变量,假设已分配 return 值。

对于 return 值的情况,假设正在对结构进行 returned,编译器可能不会将 return 值复制到堆栈,而是复制到其他位置,并且在堆栈上放置指向该位置的指针。然而,这完全取决于实施。在任何一种情况下,结构数据都被复制了两次。如果结构相对较小,则不应有可测量的差异,但如果结构有几兆字节大,则差异可能会很大。

这两个功能都没有很好的设计。这两个函数的问题是堆栈可能为空。在这种情况下,函数具有未定义的行为,很难确定是否属于这种情况。

在 C 中,更好的函数定义可以像这样

int StackTop( Stack *ps, StackEntry *pe )
{
    int success = ps->top != 0;

    if ( success )
    {
        *pe = ps->entry[ps->top-1];
    }

    return success;
}

如果您不关心函数的未定义行为,因为还有一个函数报告堆栈是否为空,那么您应该考虑另外一个函数实现,它允许更改存储在堆栈中的值。这样的函数可以看起来像

StackEntry * StackTop(Stack *ps)
{

    return &ps->entry[ps->top-1];
}