2010-05-07 18 views
6

Mam wskaźnik wskazujący na tablicę i inny wskaźnik odwołujący się do tej samej tablicy. Jak usunąć jeden z tych wskaźników bez zabicia tablicy tak, że drugi undeleted wskaźnik nadal działa?Jak usunąć wskaźnik bez usuwania danych wskazywanych przez wskaźnik?

na przykład:

int* pointer1 = new int [1000]; 
int* pointer2; 
pointer2 = pointer1; 

Teraz chcę się pozbyć pointer1, jak mogłoby zrobić to tak, że mogę nadal korzystać tablicę normalnie przez pointer2?

Odpowiedz

10

Wskaźniki te znajdują się na stosie; nie musisz ich usuwać. Po prostu zignoruj ​​pointer1 i zniknie na końcu bloku.

+1

Ahh to wyjaśnia to najlepiej dla mnie. Zatem wskaźnik jest po prostu zmienną na stosie, co ma sens. Oznacza to, że nie można uzyskać dostępu poza zakresem i nie będę go używać przypadkowo poza zakresem i powodować problemy. Ok dziękuję. – Faken

+2

@ Faken- Aby było jasne, "wskaźnik jest po prostu zmienną na stosie" nie jest prawdziwym stwierdzeniem. Wskaźnik w kodzie przykładowym jest zmienną stosu, ponieważ zadeklarowano ją statycznie. Wskaźnik można również zadeklarować dynamicznie, jak pokazuje Neil Butterworth w swoim przykładzie. Wszystko zależy od tego, jak je zadeklarujesz, nie ma nic szczególnego w tym, że obiekt jest wskaźnikiem. – bta

+3

@bta: Nie widzę niczego zadeklarowanego statycznie. Być może masz na myśli "automatyczny", rzeczywisty termin. (Oznacza to, że rzeczy nie są przydzielane w stosach, ale są przydzielane automatycznie.) – GManNickG

9

Pozwolić na wyjście poza zakres?

Nie "usuwaj" wskaźników, usuwasz to, na co wskazują. Więc jeśli chcesz po prostu pozbyć się zmiennej "pointer1", jedynym sposobem, aby to zrobić, jest zakres, w którym został utworzony, aby zostać zakończonym.

9

W ogóle nie przekazujesz tego wskaźnika do delete. Po prostu przestajesz używać tego wskaźnika. Jeśli chcesz się upewnić, że nie uzyskasz dostępu do tablicy za pomocą tego wskaźnika, możesz ustawić wartość null.

C i C++ nie śledzą, ile wskaźników wskazuje na obiekt lub tablicę. Jeśli chcesz zliczać odniesienia, musisz użyć kontenera zliczanego z referencjami, takiego jak shared_ptr, lub w tym przypadku shared_array (możesz znaleźć oba z nich w Boost i istnieje duże prawdopodobieństwo, że implementacja już je ma w <memory> w przestrzeń nazw std lub w std::tr1).

1
int** pointer1 = new int *; 
* pointer1 = new int [1000]; 
int* pointer2; 
pointer2 = * pointer1; 
delete pointer1; 
+0

Heh, byłeś dla mnie bardzo pomocny w przeszłości, ale tym razem po prostu mnie pomyliłeś, heh. – Faken

+2

@Faken Zastanów się nad lekcją Zen :-) Zasadniczo, jak wskazali inni, twoje pytanie, o które prosiłeś, nie ma zbyt wielkiego sensu. –

+0

@ Faken- Pokazuje ci, co musiałbyś zrobić, gdybyś chciał usunąć wskaźnik. Tworzy "wskaźnik do wskaźnika" i przypisuje mu adres 'int *' utworzony przez 'new'. Ponieważ 'pointer1' jest przydzielany dynamicznie w tym przypadku, możesz" zwolnić "go, gdy skończysz. Złożoność tego rozwiązania prawdopodobnie wskazuje, że trzeba ponownie przemyśleć, czy naprawdę trzeba usunąć wskaźnik. – bta

3

Jest to zmienna stos (tak, jak napisałem go), a więc związany z zakresem zadeklarowanej go. Gdy trafisz zamykający nawias klamrowy z danego zakresu, zostanie on oczyszczony bez ciebie muszą coś z tym zrobić.

Jeśli chcesz mieć absolutną pewność, że nic więcej nie będzie mogło używać wskaźnika1, możesz ustawić pointer1=NULL, gdy już to zrobisz.

4

Po statycznie zadeklarowaniu wskaźnika za pomocą int* pointer1;, użytkownik nie może zwolnić go za pomocą. Możesz tylko zwolnić przydzieloną dynamicznie pamięć, która została przydzielona przy użyciu new, malloc itd. Jedynym sposobem na pozbycie się funkcji "pointer1" jest wyjście z zakresu, na przykład po powrocie funkcji. Jeśli skończyłeś używać pointer1 i chcesz zapobiec przypadkowemu użyciu tej tablicy do zmiany tablicy, użyj pointer1 = NULL;.

1

Po prostu zignoruj ​​wskaźnik, a zniknie, gdy skończysz z funkcją lub blokiem. Pamiętaj tylko, że gdy już nie będziesz mieć jakiegoś wskaźnika, nie będzie można uzyskać do niego dostępu. Oczywiście nadal będzie tam, korzystając z pamięci, ale nie będzie można się do niej dostać. Tak więc, zanim rozważysz zwolnienie wskaźnika, upewnij się, że masz gdzieś inny wskaźnik, lub pozbędziesz się go.

4

Normalnie, aby wskaźnik był "bezpieczny", ustaw go na wartość NULL, co powoduje, że w ogóle nic nie wskazuje. Lub możesz po prostu pozwolić mu wyjść poza zakres.

Na przykład, jeśli masz dwa wskaźniki.

int *a = new int; 
int *b = a; 

// somewhere  
b = NULL; 

delete b; // does nothing now 
delete a; // deletes a 

Lub możesz pozwolić, by wypadł z zakresu.

int *a = new int; 

{ 
int *b = a; 
// blah blah blah 
} 

// don't have to worry about b 
delete a; 
+0

Czy 'b = NULL; usunąć b' coś? Czy to jest zdefiniowane? Miałem wrażenie, że to jakiś błąd lub niezdefiniowane zachowanie. –

+0

@Nathan: 'foo = NULL; delete foo; 'jest perfekcyjnie legalne i nieszkodliwe. Oznacza, że ​​nie musisz zawsze szukać nie-NULL-ness przed usunięciem. –

Powiązane problemy