2010-06-14 11 views
35

Natrafiłem na to dość nietypowe użycie "delete". Chciałbym tylko wiedzieć, czy poniższy wiersz usuwa oba wskaźniki czy tylko pierwszy?C++ Usuń składnię

delete ptr1, ptr2 
+2

tylko jako bok, usuwania słów kluczowych jest istotne tylko dla C++ i nie ma nic wspólnego z C –

Odpowiedz

47

Jest to niewątpliwie błąd. Przecinek tutaj to operator przecinka, a nie separator. Usuwany jest tylko pierwszy wskaźnik, ptr1.

Drugi wskaźnik, ptr2, jest po prostu wyrażeniem "do niczego".

Operator delete ma wyższy priorytet niż operator ,, więc wyrażenie jest analizowany tak, jakby były napisane:

(delete ptr1) , (ptr2) 

a nie tak, jakby były napisane:

delete (ptr1 , ptr2) 

Jeśli , miał wyższy priorytet niż delete, wtedy tylko wskaźnik drugi zostałby usunięty.

+0

i chociaż wynik operatora przecinek był ostatni wyraz w lista oddzielona przecinkami (tak jak twoja oryginalna odpowiedź, jeśli nie jest to ptr2, czyli del eted) czy jest tu coś trudniejszego? –

+0

@Martin: +1 do twojej odpowiedzi, ponieważ jest dość skomplikowana (obie pierwsze dwie odpowiedzi były początkowo niepoprawne, dopiero gdy napisałem przykład i przetestowałem, że zdałem sobie sprawę z pierwszeństwa). Zaktualizowałem wyjaśnienie, dlaczego pierwszy wskaźnik został usunięty. –

+0

Widziałem to po tym, jak napisałem, dobry połów. Nigdy bym nie zobaczył tego miłego twistu bez kompilatora i przypadku testowego. –

5

Tylko patrzenie na to mnie przeraża.

Nie używaj tego, nawet jeśli jest to zgodne z prawem, ponieważ większość ludzi musi przestać myśleć (i nadal będzie myliło się (jedna z dwóch pierwszych odpowiedzi musi być błędna, ponieważ są ze sobą sprzeczne, mój pierwszy instynkt jest problemy z przecinaniem (ale nie wiem))).

Nawet teraz nie odpowiedziałbym na pytanie, dopóki nie napisałem przykładu i nie przetestowałem go, a nawet wtedy bałbym się narożnych przypadków w języku, który mógłby spowodować problemy.

+2

Pisanie Lisp codziennie? Btw, zapomniałeś a): P – cwap

+0

Naprawiono (teraz więcej niż 15 znaków) :-) –

5

Rozważmy następujący przykładowy kod:

class foo 
{ 
    int _a; 
public: 
    foo(int a) : _a(a) { } 
    ~foo() { printf("~foo() %d\n", _a); } 
}; 


int main(int argc, char** argv) 
{ 
    foo *p1 = new foo(1), *p2 = new foo(2); 
    delete p1, p2; 
    return 0; 
} 

wyjście jest:

~foo() 1 

Powodem, jak już odpowiedział James, to pierwszeństwo operator.

10

James McNellis ma rację, że jest to operator przecinka, ale ma błędne pierwszeństwo operatora. On (widocznie) myśli, że to działa:

delete (ptr1, ptr2); 

w takim przypadku miałby rację - usunąłby tylko drugi element. W rzeczywistości jednak, usuwanie jest również operatorem i posiada znacznie wyższy priorytet niż operator przecinek (, która ma o tak niskie pierwszeństwa jak to możliwe), więc to nie działało jak:

(delete ptr1), ptr2; 

więc usuwa pierwszy wskaźnik, a wynikiem wyrażenia jest wartość drugiego wskaźnika - który nie został usunięty, więc nadal jest poprawny (jeśli był wcześniej).

Chciałbym powtórzyć konkluzję Martina Yorka i myślę, że to potwierdza. Wątpię, by nawet cały procent programistów C++ znał C++, a także Jamesa McNellisa - kiedy jego odpowiedź na pytanie, co konstrukcja jest błędna, jest to solidny sygnał, że prawie nikt nie będzie wiedział, co naprawdę robi. Założę się, że nikt nie może być pewien, że robi to, co było zamierzone. W rzeczywistości, przypuszczam, że miało to na celu usunięcie obu obiektów, których nie powinien wykonywać (tj. Nie będzie, chyba że kompilator ma błąd).

[Edytuj: Widzę, że podczas pisania tego, James poprawił swoją odpowiedź. Przepraszam James - ale myślę, że podstawowa konkluzja stoi, więc nie jestem usunięcie tego teraz przynajmniej]

+0

Nie trzeba przepraszać; moja oryginalna odpowiedź była całkiem błędna i z perspektywy czasu, powinienem był użyć przekreślenia podczas edycji, więc było jasne, że została edytowana w pięciominutowym oknie. –

5

nie polecam go, ale dodaje zadziała. -

delete (delete p1, p2); 

to można uogólnić w następujący sposób -

delete (delete (delete p1, p2), p3); 
delete (delete (delete (delete p1, p2), p3), p4); 
+6

To może być poprawne, ale jest całkowicie nieprzydatne do ekstremum. –

+4

Dlatego też powiedziałem, że nie poleciłbym tego ... –

+0

Szalony, ale w rzeczywistości prawdziwy – Wizard79