5

在很多例子中,我读过一个简单的 getListLength() 函数看起来像这样:

int getListLength(struct node *head)
{
    struct node *temp = head;
    int iCount = 0;

    while (temp)
    {
        ++iCount;
        temp = temp->next;
    }

    return iCount;
}

令我印象深刻的是不需要声明复制传递参数的本地指针(在本例中为 *temp)。如果我没记错的话,传递的参数会获得它们自己的副本。因此,将不需要复制 *head 的本地指针,因为 *head 本身就是副本,对吗?换句话说,丢弃 *temp 指针并在任何地方使用 head 是否正确?

4

3 回答 3

4

是的,它是副本,所以是的,它是正确的。

int getListLength(struct node* head)
{
    int iCount = 0;

    while (head)
    {
        ++iCount;
        head = head->next;
    }
    return iCount;
}

你为什么不执行它并自己看看呢?

于 2013-01-05T20:46:21.037 回答
4

虽然确实不需要本地副本,因为指针是按值传递的,但它可能出于文体原因而存在。有些人认为修改传入的参数是不好的形式(尽管我确实发现它在某些情况下很有用),但也许更重要的是,您会丢失代码中的一些自文档;具体来说,head不再总是指向链表的真正头部。这在您的一小段代码中并没有那么令人困惑,但是当代码更长和更复杂时,具有不准确命名的变量可能会更加令人困惑。

于 2013-01-05T21:01:50.630 回答
2

通常,制作传入指针的本地副本的原因是为了减少函数的副作用(通过不修改函数参数)。

如果一个函数仅使用指针来读取(而不是写入),并且与外界没有其他交互,则该函数可以在 GCC 中注释为“纯”,并且可以进行一些很好的优化。

例子:

__attribute__((pure)) int getListLength(struct node *head) 
{
    struct node *temp = head;
    int iCount = 0;

    while (temp)
    {
        ++iCount;
        temp = temp->next;
    }

    return iCount;
}

如果您不熟悉什么是副作用,请尝试阅读副作用函数式编程Wikipedia 文章以获取有关该主题的更多信息。

于 2013-01-05T21:47:53.877 回答