do koszyka |
do koszyka |
do koszyka |
do koszyka |
do koszyka |
do koszyka |
do koszyka |
do koszyka |
do koszyka |
KURS JĘZYKA C++ PODSTAWY
00. Informacje ogólne - wstęp 01. Praca z konsolą - początki - cout 02. Zmienne (int, float, double) 03. Konsola cd. - cin 04. Zmienne tekstowe - (char, string) 05. Operatory 06. Instrukcje warunkowe (if - else, switch - case) 07. Pętle (for, while) 08. Instrukcje warunkowe cd. 09. Break, Continue 10. Funkcje 11. Zakresy ważności 12. Tablice zmiennych 13. Mała powtórka :))) 14. Struct - struktury 15. String, Vector - wstęp do STL 16. Wskaźniki, referencje 16a. Wskaźnik do typów prostych 16b. Wskaźnik do funkcji 16c. Operatory new i delete 16d. Referencje 17. Pliki źródłowe i nagłówkowe Zadania powtórzeniowe 18. Class - klasy 19. Konstruktor , destruktor 20. Argumenty domyślne, przeciążanie (przeładowanie) funkcji i operatorów C++ FAQ: 01. Operacje na plikach, odczyt/zapis02. Nie działa mi polecenie gotoxy() co robić ? 03. Jaki podręcznik do nauki C++ ? ostatnia aktualizacja: 29.08.2005 WSKAŹNIKI, REFERENCJE - OPERATORY NEW I DELETE
3. Operatory new i delete.
Zarządzanie pamięcią - podstawowe informacje. W czasie pisania programu nie jesteśmy w stanie (zazwyczaj) przewidzieć ile nasz program będzie potrzebował pamięci operacyjnej komputera do działania, tu z pomocą przychodzą nam operatory new i delete dzięki nim możemy przydzielać i zwalniać pamięć. Aby przydzielić pamięć należy: - utworzyć wskaźnik określonego typu który będzie zawierał adres bloku przydzielonej pamięci - wykonać przydzielanie pamięci - wykonać sprawdzenie czy pamięć została przydzielona Cały proces jest przedstawiony na poniższym rysunku: 1 - tworzymy wskaźnik w którym będzie zapisany adres przydzielonej pamięci 2 - przydzielanie pamięci - do wskaźnika o nazwie pi_Tablica przypisz adres uzyskany z przydzielania pamięci operatorem new, przydzielamy obszar dla danych typu int o rozmiarze 50 (miejsce na 50 elementów) 3 - sprawdź czy we wskaźniku jest liczba 0 (zero) - jeśli w czasie przydzielania pamięci wystąpił błąd i pamięć nie mogła zostać przydzielona, wskaźnik zawiera właśnie adres zero, w przeciwnym wypadku wskaźnik będzie zawierał adres naszego przydzielonego obszaru pamięci. Często spotykany jest także zapis w postaci: if (pi_Tablica == NULL) , NULL zazwyczaj oznacza zero ale nie zawsze jest to oczywiste więc tego typu zapisu raczej powinno się unikać - nie jest on błędny ale w przyszłości może prowadzić do pewnych niejednoznaczności. 4 - ta część programu zostanie wykonana w przypadku błędu (pamięć nie została przydzielona) 5 - ta część zostanie wykonana w przypadku powodzenia pamięć została przydzielona, w powyższym przykładzie program nie korzysta z przydzielonej pamięci tylko od razu ją zwalnia. Zwalniania pamięci dokonujemy operatorem delete, powyższy zapis mówi nam: zwolnij blok ([]) pamięci którego adres jest zapisany we wskaźniku pi_Tablica. Przy zwalnianiu pamięci obowiązuje zasada, że jeśli przydzielana pamięć była tablicą elementów określonego typu (była podana jawnie ilość elementów w nawiasach []) to taki obszar pamięci należy zwalniać także jako blok czyli: delete [] pi_Tablica, natomiast jeśli pamięć była przydzielana na tylko 1 element danego typu: pi_Tablica = new int; to zwalniamy ją także jako pojedynczy element: delete pi_Tablica (zwróć uwagę na brak nawiasów [] ) Istotne uzupełnienia - powyższe przykłady bazowały na zmiennej typu int, ale operację przydzielania pamięci można przeprowadzać dla praktycznie dowolnych typów prostych jak i złożonych (np. strukury) - w czasie przydzielania pamięci w najprostszym modelu mamy dostępne następujące możliwości: pi_Tablica = new int[50]; - przydzielenie pamięci na 50 elementów typu int pi_Tablica = new int(50); - przydzielenie pamięci na jedną zmienną typu int oraz wpisanie do niej od razu liczby 50 pi_Tablica = new int; - przydzielenie pamięci na jedną zmienną typu int, jej wartość początkowa nie jest ustalona (jest losowa) - w momencie przydzielania pamięci system wyszukuje pierwszy wolny kawałek pamięci i przydziela go do naszych potrzeb, należy zwrócić uwagę na to, że w tej pamięci wcześniej mogły być jakieś dane więc przydzielony nam obszar należy NAJPIERW wyczyścić zanim zaczniemy z niego korzystać - przydzieloną pamięć należy ZAWSZE zwolnić gdy nie jest już potrzebna (lub ostatecznie przy kończeniu pracy programu), wyobraź sobie sytuację gdy twój program przydziela sobie np. 155 razy pamięć po 1MB nie zwalniając jej, 155MB pamięci systemowej jest zablokowane i nie może być używane przez inne programy - wskaźnik jest jedynym miejscem gdzie jest zapisany adres przydzielonej pamięci, jeśli zrobimy coś takiego: pi_Tablica = new int[200]; a następnie pi_Tablica = new int[120]; to obszar przydzielony jako pierwszy (200 elementów) jest praktycznie bezpowrotnie utracony zarówno dla naszego programu jak i systemu operacyjnego (aż do ponownego restartu komputera), teoretycznie system powinien zadbać o to aby pamięć przydzielona przez jakiś program w momencie zakańczania jego pracy była zwalniana - często tak się dzieje ale nie czarujmy się lepiej samemu zadbać o prawidłowe zwalnianie pamięci unikniemy w ten sposób przykrych niespodzianek - na wskaźnikach możemy przeprowadzać operacje arytmetyczne (można je m.in. dodawać i odejmować), np. dopuszczalny jest taki zapis: pi_Tablica++; mówi nam on: przestaw wskaźnik na kolejny element tablicy (tu uwaga - wskaźnik jest to adres w pamięci i jeśli np wskaźnik zawiera adres 1000 i pracujemy na tablicy typu int to zostanie on zwiększony o 4 na adres 1004 (int w systemie windows zajmuje 4 bajty), natomiast jeśli pracujemy na danych typu char to adres z 1000 zostanie zwiększony na 1001 (char to 1 bajt), najlepiej zawsze sprawdzać rozmiar typu na którym pracujemy operatorem sizeof (np sizeof(int)) zanim tak się wkopiemy, że kompletnie nie będziemy wiedzieli co i gdzie nasz program robi :) ) |
|