Zawsze zastanawiałem się, dlaczego automatyczne ustawienie wskaźnika na NULL po usunięciu nie jest częścią standardu. Jeśli zostanie to rozwiązane, wiele awarii z powodu nieprawidłowego wskaźnika nie wystąpi. Powiedziawszy jednak, że przychodzi mi do głowy kilka powodów, dla których norma miałaby to ograniczyć:
Występ:
Dodatkowa instrukcja może spowolnić
delete
działanie.Czy to może być spowodowane
const
wskazówkami.Z drugiej strony, myślę, że standard mógłby coś zrobić w tym szczególnym przypadku.
Czy ktoś zna dokładne powody, dla których na to nie pozwala?
Po pierwsze, ustawienie wartości null wymagałoby zmiennej przechowywanej w pamięci. To prawda, że zwykle masz wskaźnik w zmiennej, ale czasami możesz chcieć usunąć obiekt pod właśnie obliczonym adresem. Byłoby to niemożliwe przy „anulowaniu” usuwania.
Potem przychodzi wydajność. Być może napisałeś kod w taki sposób, że wskaźnik wyjdzie poza zakres natychmiast po zakończeniu usuwania . Wypełnienie go zerami to tylko strata czasu. A C ++ to język z ideologią "nie potrzebujesz tego? Wtedy nie musisz za to płacić".
Jeśli potrzebujesz bezpieczeństwa, masz do dyspozycji szeroką gamę inteligentnych wskazówek lub możesz napisać własne - lepsze i sprytniejsze.
źródło
delete (ptr + i)
Możesz mieć wiele wskaźników wskazujących na tę pamięć. Stworzyłoby to fałszywe poczucie bezpieczeństwa, gdyby wskaźnik określony do usunięcia został ustawiony na null, ale wszystkie inne wskaźniki nie. Wskaźnik to nic innego jak adres, liczba. Równie dobrze może to być int z operacją wyłuskiwania. Chodzi mi o to, że musiałbyś również przeskanować każdy pojedynczy wskaźnik, aby znaleźć te, które odwołują się do tej samej pamięci, którą właśnie usunąłeś, i je również usunąć. Przeszukanie wszystkich wskaźników dla tego adresu i ich wyeliminowanie wymagałoby dużej mocy obliczeniowej, ponieważ język nie jest do tego przeznaczony. (Chociaż niektóre inne języki układają swoje odniesienia, aby osiągnąć podobny cel w inny sposób).
źródło
Wskaźnik można zapisać w więcej niż jednej zmiennej, ustawienie jednej z nich na NULL nadal pozostawiłoby nieprawidłowe wskaźniki w innych zmiennych. Więc tak naprawdę niewiele zyskujesz, bardziej prawdopodobne jest, że stworzysz fałszywe poczucie bezpieczeństwa.
Poza tym możesz stworzyć własną funkcję, która robi to, co chcesz:
template<typename T> void deleten(T *&ptr) { delete ptr; ptr = NULL; }
źródło
Ponieważ tak naprawdę nie ma takiej potrzeby, a ponieważ wymagałoby to usunięcia, przyjmując wskaźnik do wskaźnika, a nie tylko wskaźnik.
źródło
delete
jest używany głównie w destruktorach, w takim przypadku ustawienie elementu na NULL jest bezcelowe. Kilka linijek później, na zakończenie}
, członek już nie istnieje. W operatorach przypisania po usunięciu zwykle i tak następuje przypisanie.Ponadto spowodowałoby to, że następujący kod byłby nielegalny:
T* const foo = new T; delete foo;
źródło
Oto kolejny powód; załóżmy, że delete ustawia swój argument na NULL:
int *foo = new int; int *bar = foo; delete foo;
Czy pasek powinien zostać ustawiony na NULL? Czy możesz to uogólnić?
źródło
Jeśli masz tablicę wskaźników, a drugą czynnością jest usunięcie pustej tablicy, nie ma sensu ustawiać każdej wartości na null, gdy pamięć ma zostać zwolniona. Jeśli chcesz, aby był pusty .. napisz do niego null :)
źródło
C ++ pozwala na zdefiniowanie własnego operatora new i delete, aby na przykład używał własnego alokatora puli. Jeśli to zrobisz, możesz użyć new i delete z rzeczami, które nie są ściśle adresami, ale mówią indeksy w tablicy puli. W tym kontekście wartość NULL (0) może mieć znaczenie prawne (odnosząc się do pierwszej pozycji w puli).
Zatem automatyczne ustawienie parametru delete na NULL nie zawsze ma znaczenie - ustawia wartość na nieprawidłową wartość. Nieprawidłowa wartość nie zawsze może wynosić NULL.
źródło
Filozofia C ++ to „płać za to tylko wtedy, gdy go używasz”. Myślę, że to może odpowiedzieć na twoje pytanie.
Czasami możesz mieć własną stertę, która odzyska usuniętą pamięć ... lub czasami wskaźnik nie jest własnością żadnej zmiennej. Lub wskaźnik przechowywany w kilku zmiennych - można wyzerować tylko jedną z nich.
Jak widać, ma wiele problemów i możliwych problemów.
źródło
Automatyczne ustawienie wskaźnika na NULL nie rozwiązałoby większości problemów związanych z niewłaściwym użyciem wskaźnika. Jedyną awarią, której by uniknąć, jest dwukrotna próba usunięcia. A co, jeśli wywołasz funkcję składową na takim wskaźniku? Nadal by się zawiesił (zakładając, że uzyskuje dostęp do zmiennych składowych). C ++ nie ogranicza możliwości wywoływania żadnej funkcji na wskaźnikach NULL, ani nie powinien tego robić z punktu widzenia wydajności.
źródło
Widzę ludzi, którzy udzielają dziwnych odpowiedzi na to pytanie.
ptr = NULL; W jaki sposób takie proste stwierdzenie może spowodować opóźnienie wydajności?
Inna odpowiedź mówi, że możemy mieć wiele wskaźników wskazujących na to samo miejsce w pamięci. Na pewno możemy. W tym przypadku operacja usuwania na jednym wskaźniku spowodowałaby, że tylko ten wskaźnik miałby wartość NULL (gdyby usuwanie powodowało, że wskaźnik miał wartość NULL), a drugi wskaźnik byłby inny niż NULL i wskazywał na wolne miejsce w pamięci.
Rozwiązanie powinno polegać na tym, że użytkownik powinien usunąć wszystkie wskaźniki wskazujące na tę samą lokalizację. Wewnętrznie powinien sprawdzić, czy pamięć jest już zwolniona, niż nie zwolnić. Tylko ustaw wskaźnik na NULL.
Stroustrup mógł zaprojektować usuwanie, aby działało w ten sposób. Myślał, że zajmą się tym programiści. Więc zignorował.
źródło