> C++ dynamiczna alokacja/rezerwacja/przydział pamięci Dane: Iwona Polak iwona.polak@us.edu.pl Uniwersytet Śląski Instytut Informatyki 1429536600
> Dzisiejsze zajęcia sponsorują słówka: new oraz delete ++ dynamiczna alokacja/rezerwacja/przydział pamięci 2 / 16
> Stos i sterta Stos przechowuje m.in. zmienne globalne, zmienne statyczne, parametry funkcji. Sterta wydzielony obszar wolnej pamięci kontrolowany ręcznie przez programistę, przeznaczony do przechowywania danych dynamicznych. C++ dynamiczna alokacja/rezerwacja/przydział pamięci 3 / 16
> Dynamiczna alokacja/rezerwacja/przydział pamięci char *wskaznik; wskaznik = new char; *wskaznik = A ; delete wskaznik; // utworzenie obiektu // ten obiekt nie ma nazwy, // tylko adres przypisany do wskaznik // likwidacja obiektu ++ dynamiczna alokacja/rezerwacja/przydział pamięci 4 / 16
> Dynamiczna alokacja/rezerwacja/przydział pamięci char *wskaznik; wskaznik = new char; *wskaznik = A ; delete wskaznik; // utworzenie obiektu // ten obiekt nie ma nazwy, // tylko adres przypisany do wskaznik // likwidacja obiektu float *w; w = new float [16]; w[0] = 3.14; delete [] w; // dla tablic: // wskaźnik definiujemy jak zwykle // dodajemy rozmiar tablicy // przy likwidacji trzeba pamiętać // o nawiasach kwadratowych ++ dynamiczna alokacja/rezerwacja/przydział pamięci 4 / 16
Do każdego new powinno być jedno delete. C++ dynamiczna alokacja/rezerwacja/przydział pamięci 5 / 16
> Na rozgrzewkę Zadeklaruj wskaźnik a typu całkowitoliczbowego. Następnie: * Użyj słowa kluczowego new, aby przydzielić pamięć i stworzyć dynamiczny obiekt, na który będzie wskazywać a. * Przypisz do obiektu wartość 64. * Wyświetl adres przechowywany w a. * W osobnym wierszu wyświetl wartość z a. * Usuń dynamicznie przydzieloną pamięć przy pomocy słowa kluczowego delete. C++ dynamiczna alokacja/rezerwacja/przydział pamięci 6 / 16
> Cechy obiektów stworzonych operatorem new 1. My decydujemy o czasie ich życia (od new do delete). 2. Nie mają nazwy. (Możemy nimi operować tylko poprzez wskaźniki). 3. Nie obowiązują ich zwykłe zasady o zakresie ważności. (Mamy wskaźnik, który na obiekt pokazuje = mamy dostęp). 4. Zaraz po utworzeniu tkwią w nich jeszcze śmieci. C++ dynamiczna alokacja/rezerwacja/przydział pamięci 7 / 16
> I jeszcze raz int *tab; tab = new int [rozmiar]; // lub razem: int *tab = new int [rozmiar]; // np. cout << "Ile elementow ma miec tablica?"<< endl; int rozmiar; cin >> rozmiar; int *tab = new int[rozmiar]; // utworzenie tablicy o rozmiarze podanym przez użytkownika... delete [] tab; // likwidacja tablicy tab = NULL; // dla bezpieczeństwa ++ dynamiczna alokacja/rezerwacja/przydział pamięci 8 / 16
> I jeszcze raz int *tab; tab = new int [rozmiar]; // lub razem: int *tab = new int [rozmiar]; // np. cout << "Ile elementow ma miec tablica?"<< endl; int rozmiar; cin >> rozmiar; int *tab = new int[rozmiar]; // utworzenie tablicy o rozmiarze podanym przez użytkownika... delete [] tab; // likwidacja tablicy tab = NULL; // dla bezpieczeństwa Programista musi kontrolować zakres tablicy i poprawność indeksów! C++ dynamiczna alokacja/rezerwacja/przydział pamięci 8 / 16
Do każdego new powinno być C++ dynamiczna alokacja/rezerwacja/przydział pamięci 9 / 16
Do każdego new powinno być jedno delete. C++ dynamiczna alokacja/rezerwacja/przydział pamięci 9 / 16
Do każdego new powinno być jedno delete. ZAWSZE. C++ dynamiczna alokacja/rezerwacja/przydział pamięci 9 / 16
> Ćwiczenie czyni mistrza 1. Napisz program, który pyta użytkownika o liczbę naturalną, maksymalnie 25 (musisz to zweryfikować). Na tej podstawie tworzy tablicę tej wielkości (alokowaną dynamicznie). Do tablicy wczytuje kolejno liczby podane przez użytkownika. Po podaniu wszystkich liczb: * liczby na indeksach parzystych zamienia na dodatnie, * liczby na indeksach nieparzystych zamienia na ujemne. Następnie należy wydrukować wszystkie liczby na ekranie. 2. Napisz program, który tworzy tablicę (alokowaną dynamicznie) o wielkości wylosowanej z przedziału <16,32>. Następnie wypełnia ją kolejnymi potęgami dwójki, zaczynając od 2 0 dla indeksu 0. Na koniec wydrukuj zawartość tablicy na ekran w następujący sposób: [0] 2ˆ0 = 1 [1] 2ˆ1 = 2 [2] 2ˆ2 = 4 itd. C++ dynamiczna alokacja/rezerwacja/przydział pamięci 10 / 16
> Zagadka Co tu się wyświetli? ++ dynamiczna alokacja/rezerwacja/przydział pamięci 11 / 16
> Zagadka Co tu się wyświetli? A jak się dostać do obiektu 50? ++ dynamiczna alokacja/rezerwacja/przydział pamięci 11 / 16
> Zagadka Co tu się wyświetli? A jak się dostać do obiektu 50? STRACONY! :-( ++ dynamiczna alokacja/rezerwacja/przydział pamięci 11 / 16
> Tablice dwuwymiarowe Zapis typ_zmiennej *tablica=new typ_zmiennej[x][y]; nie stworzy tablicy dwuwymiarowej. Trzeba inaczej: C++ dynamiczna alokacja/rezerwacja/przydział pamięci 12 / 16
> Tablice dwuwymiarowe Zapis typ_zmiennej *tablica=new typ_zmiennej[x][y]; nie stworzy tablicy dwuwymiarowej. Trzeba inaczej: Czego tu brakuje? C++ dynamiczna alokacja/rezerwacja/przydział pamięci 12 / 16
> Tablice dwuwymiarowe (i nie tylko) Prawidłowa konstrukcja (oraz destrukcja) (3 x 4) char **tab = new char*[3]; for (size_t i = 0; i < 3; i++) tab[i] = new char[4];... tab[0][2] = 128;... for (size_t i = 0; i < 3; i++) delete[] tab[i]; delete[] tab; ++ dynamiczna alokacja/rezerwacja/przydział pamięci 13 / 16
> Tablice dwuwymiarowe (i nie tylko) Prawidłowa konstrukcja (oraz destrukcja) (3 x 4) char **tab = new char*[3]; for (size_t i = 0; i < 3; i++) tab[i] = new char[4];... tab[0][2] = 128;... for (size_t i = 0; i < 3; i++) delete[] tab[i]; delete[] tab; Kolejne wymiary: analogicznie. C++ dynamiczna alokacja/rezerwacja/przydział pamięci 13 / 16
> Tablice dwuwymiarowe (i nie tylko) Prawidłowa konstrukcja (oraz destrukcja) (3 x 4) char **tab = new char*[3]; for (size_t i = 0; i < 3; i++) tab[i] = new char[4];... tab[0][2] = 128;... for (size_t i = 0; i < 3; i++) delete[] tab[i]; delete[] tab; Kolejne wymiary: analogicznie. C++ dynamiczna alokacja/rezerwacja/przydział pamięci 13 / 16
> Wyższy wymiar ćwiczeń 1. Stwórz trójwymiarową tablicę dynamiczną. 2. Stwórz tablicę trójkątną o dowolnym rozmiarze i wypełnij ją kolejnymi wartościami zgodnie ze wzorem: 1 2 2 3 3 3 4 4 4 4 itd. 3. Ułóż program obliczający sumę S elementów o indeksach parzystych tabeli dwuwymiarowej. Dla tabeli T [4][5] będzie to suma S = T [0][0] + T [0][2] + T [0][4] + T [2][0] + T [2][2] + T [2][4]. Wielkość tabeli jest pobierana od użytkownika i wypełniana losowymi liczbami całkowitymi. (Oczywiście pamięć ma być przydzielona dynamicznie.) ++ dynamiczna alokacja/rezerwacja/przydział pamięci 14 / 16
> Ćwiczenie (trochę bardziej rozbudowane) 1. 1.1 Zadeklaruj strukturę składającą się z trzech pól: double, int oraz char. 1.2 Napisz funkcję przyjmującą jeden parametr (wskaźnik na utworzoną przez siebie strukturę) i pozwalającą na ustawienie wszystkich trzech pól wartościami przeczytanymi od użytkownika z klawiatury. 1.3 Napisz funkcję wypisującą wartości elementów struktury (przykładowe wyjście: 2.5 10 A ). 1.4 W funkcji main(): 1.4.1 Zainicjuj generator liczb pseudolosowych. 1.4.2 Pobierz od użytkownika wartość typu int. 1.4.3 Zadeklaruj dynamicznie alokowaną tablicę o rozmiarze pobranym od użytkownika w poprzednim podpunkcie. 1.4.4 Wypełnij wszystkie pola wszystkich struktur w tablicy wartościami losowymi. 1.4.5 Wypisz całą tablicę struktur na ekran. W tym celu użyj funkcji napisanej w punkcie 3. ++ dynamiczna alokacja/rezerwacja/przydział pamięci 15 / 16
> Wycieki pamięci i wiszące wskaźniki /* zmienna na stercie, do której nie mamy żadnego wskaźnika */ void fun() { int *wsk = new int; //rezerwacja pamięci na liczbę typu int *wsk = 20; //wpisanie w zarezerwowane miejsce wartości } // po wyjściu z funkcji *wsk już nie istnieje, // ale pamięć dalej jest zaalokowana /* wskaźnik odnoszący się do zmiennej, która została już zdealokowana */ int *wsk = new int; //rezerwacja pamięci na liczbę typu int delete wsk; //dealokacja zmiennej C++ dynamiczna alokacja/rezerwacja/przydział pamięci 16 / 16