2012-03-20 14 views
7
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 
} 

To jest fragment kodu z "Algorithm in C++" autorstwa Roberta Sedgewicka, strona 252, Program 5.19. W funkcji max() zwróconą zmienną jest wskaźnik, który jest tworzony wewnątrz funkcji.Zwróć lokalny wskaźnik

Moim zdaniem, zwracanie wskaźnika lokalnego nie jest dozwolone w języku c/C++. Więc moje pytanie brzmi: "czy to jest w porządku, aby napisać taką funkcję"? Nie mogę uwierzyć, że taka klasyczna książka popełnia taki błąd. Czy źle zrozumiałem zasadę? Proszę o pomoc. Dzięki.

+0

'link x = nowy węzeł (a [m]);'! = Wskaźnik lokalny – Mysticial

+1

@Mysticial: Pedantically mówiąc, to * jest * lokalnym wskaźnikiem, ale nie wskazuje na lokalny obiekt :-) –

+0

W 'c' zwraca wskaźnik do zmiennej lokalnej, w wyniku czego pojawia się ostrzeżenie i prawdopodobnie należy tego uniknąć, chyba że wiesz, co robisz, ale to zadziała. Nie jestem pewien, czy 'C++' zmienia to na błąd. – twain249

Odpowiedz

5

x nie jest "wskaźnikiem lokalnym" - czyli wskaźnikiem do zmiennej lokalnej. *x został przydzielony przy użyciu new. x wskazuje na dynamicznie przydzieloną pamięć i zwracanie tego wskaźnika jest w porządku. Więc tak, można napisać taką funkcję, i nie ma w niej błędu.

3

Jest to błąd zwracania wskaźnika do zmiennej lokalnej. x punkty do zmiennej przydzielonej na stercie:

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

Zatem x nie jest skierowany do zmiennej lokalnej.

Powodem, dla którego zwracanie wskaźnika do zmiennej lokalnej jest błędem, jest to, że taka zmienna istnieje tylko tak długo, jak długo funkcja jest aktywna (tj. Pomiędzy wprowadzeniem a zakończeniem). Zmienne przydzielone na stercie (na przykład przy użyciu operatora new) istnieją, dopóki nie zostaną zwolnione (np. Za pomocą operatora delete).

+0

Tak więc pamięć przydzielona do x nie zostanie zwolniona, dopóki nie zostanie to wyraźnie zrobione. Czy mogę powiedzieć, że pamięć przydzielona na stosie funkcji będzie niezdefiniowana, jeśli zmienna wykracza poza zakres; ale na kupie nie będzie? –

+0

Tak. Potrzebujesz wyraźnej dezalokacji. Ponadto zmienna przydzielona na stercie będzie nadal istnieć po powrocie z funkcji, która go przydzieliła. –

1

Jest to całkowicie w porządku, ponieważ zawartość x jest przydzielana na stercie, a nie na stosie. Być może dezorientujesz się, ponieważ istnieje tam typedef node* link;, co sprawia, że ​​wygląda jak przydział stosu, ponieważ maskuje fakt, że x jest w rzeczywistości node *.

+1

'x' jest zmienną automatyczną. Być może myślałeś o '* x'. –

+0

@KerrekSB tak, przypuszczam, że miałem na myśli "zawartość' x' są przydzielane na stercie ", edytowane dla jasności. – jli

+0

W rzeczywistości zawartość 'x' jest zawartością zmiennej automatycznej. Być może myślałeś o zawartości '* x'? –