返回本地指针

8
struct node
{
  Item item; node *l, *r;
  node(Item x) {item = x; l = 0; r = 0;}
};

typedef node* link;
link max(Item a[], int l, int r)
{
    int m = (l+r)/2;
    link x = new node(a[m]);
    if (l==r) return x; // return a local pointer
    x->l = max(a, l, m);
    x-r = max(a, m+1, r);
    Item u = x->l->item, v = x->r->item;
    if (u>v) x->item = u;
    else x->item=v;

    return x;    // return a local pointer
}

这是《C++算法》一书第252页5.19程序中的一段代码。在函数max()中,返回的变量是在函数内部创建的指针。
据我所知,在C/C++中不允许返回局部指针。因此我的问题是:“这样写一个函数是否可行?”我无法相信这样经典的书籍会犯这样的错误。或者是我理解有误? 请帮忙解答。谢谢。

1
@Mysticial:严谨地说,它确实是一个本地指针,但它并不指向本地对象 :-) - Kerrek SB
c 中返回指向本地变量的指针会导致警告,除非你知道自己在做什么,否则应该避免这样做,但它确实可以工作。不确定 c++ 是否将其改为错误。 - twain249
1
@twain249:这不是C++中的错误。你是说C标准规定了诊断吗?你有参考资料吗? - Kerrek SB
@KerrekSB,我刚刚写了一个这样的函数 int *fun() { int a = 3; return &a;} 并使用gcc编译它,看看会发生什么,结果我得到了一个警告。所以我想我能确定的是gcc对此会发出警告。 - twain249
1
@twain249:这些都很有启发性,但我认为“通过我的编译器所做的”证明不足以作为关于C标准的陈述。 - Kerrek SB
显示剩余2条评论
3个回答

5

x 不是一个“本地指针” - 也就是说,它不是指向本地变量的指针。 *x 是使用new分配的。 x 指向动态分配的内存,返回该指针是可以的。 因此,编写这样一个函数是可以的,书中没有错误。


4

返回指向本地变量的指针是一个错误。 x 指向在堆上分配的变量:

link x = new node(a[m]);

因此,x指向的不是本地变量。返回指向本地变量的指针是一个错误的原因是,这样的变量仅存在于函数活动期间(即在进入和退出之间)。在堆上分配的变量(例如使用new运算符)存在直到它们被释放为止(例如使用delete运算符)。

1
因此,分配给x的内存将不会被释放,直到我们明确执行此操作。或者我可以说,如果变量超出范围,分配在函数堆栈上的内存将是未定义的;但在堆上分配的内存则不会。 - Ke Li
1
是的,您确实需要显式释放。此外,在堆上分配的变量将在分配它的函数返回后继续存在。 - Adam Zalcman

1

这是完全没问题的,因为x的内容是在堆上分配的,而不是在栈上。你可能会感到困惑,因为其中有一个typedef node* link;,使它看起来像是一个栈分配,因为它掩盖了x实际上是一个node *的事实。


1
x 是一个自动变量。你可能在想 *x - Kerrek SB
@KerrekSB 是的,我想我是指“x的内容在堆上分配”,为了更清晰已进行编辑。 - jli
实际上,x 的内容是自动变量的内容。也许您想的是 * x 的内容? - Kerrek SB
@KerrekSB 我猜我们对“内容”的定义不同,我想你的可能更正确。 - jli

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接