C++/Zarządzanie pamięcią: Różnice pomiędzy wersjami
m linki do malloc i free |
Tworzenie tablic wielowymiarowych |
||
Linia 9: | Linia 9: | ||
Od razu widać, że drugi zapis jest zdecydowanie łatwiejszy i przyjemniejszy w użyciu. To jest podstawowa zaleta operatora new - krótszy zapis. Wystarczy wiedzieć jakiego typu ma być obiekt, który chcemy powołać do życia, nie martwiąc się o rozmiar alokowanego bloku pamięci. |
Od razu widać, że drugi zapis jest zdecydowanie łatwiejszy i przyjemniejszy w użyciu. To jest podstawowa zaleta operatora new - krótszy zapis. Wystarczy wiedzieć jakiego typu ma być obiekt, który chcemy powołać do życia, nie martwiąc się o rozmiar alokowanego bloku pamięci. Za pomocą operatora new można również tworzyć tablice wielowymiarowe: |
||
int **Wektory = new int *[5]; |
|||
for( int i=0; i<5; i++ ) |
|||
⚫ | |||
Wektory[i] = new int [10]; |
|||
⚫ | |||
W ten sposób stworzono tablicę dwuwymiarową którą statycznie zadeklarowalibyśmy jako: |
|||
int Wektory[5][10]; |
|||
Ilość elementów poszczególnych wymiarów nie musi być jednakowa. Można np zadeklarować tablicę taką: |
|||
int **Wektory = new int *[2]; |
|||
Wektory[0] = new int [5]; |
|||
Wektory[1] = new int; |
|||
Przy takiej deklaracji pierwszy wiersz ma 5 elementów (tablica) a drugi to jeden element. |
|||
Deklaracja tablic więcej wymarowych przebiega podobnie: |
|||
int ***Wektory = NULL; // deklarujemy tablicę 3-wymiarową |
|||
Wektory = = new int **[5]; // pierwszy wymiar |
|||
Wektory[0] = new int *[10]; // pierwszy element pierwszego wymiaru |
|||
Wektory[1] = new int *[3]; // drugi element pierwszego wymiaru |
|||
.... |
|||
Wektory[0][1] = new int [3] // wymiar I = 0 -> wymiar II = 1 -> 3 elementy(tablica) |
|||
Wektory[0][3] = new int [5] // wymiar I = 0 -> wymiar II = 3 -> 5 elementów(tablica) |
|||
Wektory[1][2] = new int; // wymiar I = 1 -> wymiar II = 2 -> 1 element |
|||
... |
|||
Stosując ten algorytm ogólnie można deklarować tablice n-wymiarowe bez większego problemu. |
|||
Usuwanie tablic wielowymiarowych przebiega podobnie jak jednowymiarowych z tą różnicą, że usuwanie zaczynamy od "najgłębszego" wymiaru: |
|||
int ***Wektory = new int **[2]; |
|||
Wektory[0] = new int *[2]; |
|||
Wektory[1] = new int *[2]; |
|||
Wektory[0][0] = new int; // pojedyńcza zmienna dynamniczna! nie tablica |
|||
Wektory[0][1] = new int [5]; // zmienna tablicowa |
|||
Wektory[1][0] = new int [3]; |
|||
Wektory[1][1] = new int [2]; |
|||
... |
|||
// Kod programu |
|||
... |
|||
// III wymiar |
|||
delete Wektory[0][0]; // kasujemy pojedyńczą zmienną |
|||
delete [] Wektory[0][1]; |
|||
delete [] Wektory[1][0]; |
|||
delete [] Wektory[1][1]; |
|||
// II wymiar |
|||
delete [] Wektory[0]; |
|||
delete [] Wektory[1]; |
|||
// I wymiar |
|||
delete [] Wektory; |
|||
Zwrócić uwagę trzeba na dwie rzeczy: |
|||
<ol> |
|||
<LI>'''delete []''' używamy dla zmiennych tablicowych a '''delete''' dla pojedyńczych zmiennych</li> |
|||
<LI>Kolejność zwalniania wymiarów jest odwrotna niż ich tworzenia</LI> |
|||
</ol> |
|||
Drugą zaletą jest fakt, że przy okazji alokacji pamięci możemy wywołać odpowiedni konstruktor inicjalizując wartości zmiennych obiektu, np. |
|||
Test *Test = new Test(1,2); |
|||
⚫ | |||
⚫ | |||
{{ProstaNawigacja|poprz=Przeciążanie funkcji |poprzart=C++:Przeciążanie_funkcji |nast=Czym_jest_obiekt|nastart=C++:Czym_jest_obiekt|spis=Programowanie:C++}} |
{{ProstaNawigacja|poprz=Przeciążanie funkcji |poprzart=C++:Przeciążanie_funkcji |nast=Czym_jest_obiekt|nastart=C++:Czym_jest_obiekt|spis=Programowanie:C++}} |
Wersja z 23:03, 27 mar 2006
W języku C++ do alokowania pamięci służy operator new a do zwalniania - delete. W C++ można również stosować funkcje malloc i free, jednak należy być ostrożnym. Najczęstszym błędem jest mieszanie operatorów new i delete z funkcjami malloc i free , np. zwalnianie pamięci zaalokowanej przez new przy pomocy free.
Rozważmy prosty przykład. Załóżmy, że chcemy stworzyć wektor 10 liczb typu całkowitego. Możemy to zrobić na dwa sposoby.W stylu znanym z języka C:
int *Wektor = (int*)malloc(sizeof(int)*10); free(Wektor);
albo w stylu C++:
int *Wektor = new int[10]; delete Wektor;
Od razu widać, że drugi zapis jest zdecydowanie łatwiejszy i przyjemniejszy w użyciu. To jest podstawowa zaleta operatora new - krótszy zapis. Wystarczy wiedzieć jakiego typu ma być obiekt, który chcemy powołać do życia, nie martwiąc się o rozmiar alokowanego bloku pamięci. Za pomocą operatora new można również tworzyć tablice wielowymiarowe:
int **Wektory = new int *[5]; for( int i=0; i<5; i++ ) Wektory[i] = new int [10];
W ten sposób stworzono tablicę dwuwymiarową którą statycznie zadeklarowalibyśmy jako:
int Wektory[5][10];
Ilość elementów poszczególnych wymiarów nie musi być jednakowa. Można np zadeklarować tablicę taką:
int **Wektory = new int *[2]; Wektory[0] = new int [5]; Wektory[1] = new int;
Przy takiej deklaracji pierwszy wiersz ma 5 elementów (tablica) a drugi to jeden element.
Deklaracja tablic więcej wymarowych przebiega podobnie:
int ***Wektory = NULL; // deklarujemy tablicę 3-wymiarową Wektory = = new int **[5]; // pierwszy wymiar Wektory[0] = new int *[10]; // pierwszy element pierwszego wymiaru Wektory[1] = new int *[3]; // drugi element pierwszego wymiaru .... Wektory[0][1] = new int [3] // wymiar I = 0 -> wymiar II = 1 -> 3 elementy(tablica) Wektory[0][3] = new int [5] // wymiar I = 0 -> wymiar II = 3 -> 5 elementów(tablica) Wektory[1][2] = new int; // wymiar I = 1 -> wymiar II = 2 -> 1 element ...
Stosując ten algorytm ogólnie można deklarować tablice n-wymiarowe bez większego problemu.
Usuwanie tablic wielowymiarowych przebiega podobnie jak jednowymiarowych z tą różnicą, że usuwanie zaczynamy od "najgłębszego" wymiaru:
int ***Wektory = new int **[2]; Wektory[0] = new int *[2]; Wektory[1] = new int *[2]; Wektory[0][0] = new int; // pojedyńcza zmienna dynamniczna! nie tablica Wektory[0][1] = new int [5]; // zmienna tablicowa Wektory[1][0] = new int [3]; Wektory[1][1] = new int [2]; ... // Kod programu ... // III wymiar delete Wektory[0][0]; // kasujemy pojedyńczą zmienną delete [] Wektory[0][1]; delete [] Wektory[1][0]; delete [] Wektory[1][1]; // II wymiar delete [] Wektory[0]; delete [] Wektory[1]; // I wymiar delete [] Wektory;
Zwrócić uwagę trzeba na dwie rzeczy:
- delete [] używamy dla zmiennych tablicowych a delete dla pojedyńczych zmiennych
- Kolejność zwalniania wymiarów jest odwrotna niż ich tworzenia
Drugą zaletą jest fakt, że przy okazji alokacji pamięci możemy wywołać odpowiedni konstruktor inicjalizując wartości zmiennych obiektu, np.
Test *Test = new Test(1,2);
zakładając, że obiekt Test posiada dwie zmienne typu całkowitego i zdefiniowany konstruktor Test(int,int).
Kolejną korzyścią jest możliwość przeciążania. Jednak to już jest temat na inny rozdział.