plik


[Kurs C++] XIX. Dynamiczne zarządzanie pamięcią new i delete var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www."); document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E")); var pageTracker = _gat._getTracker("UA-3650348-1"); pageTracker._initData(); pageTracker._trackPageview(); Serwis został przeniesiony pod nową domenę: http://cpp0x.pl/ Strona główna Kursy Artykuły Forum Pliki Promuj Nas! PowrótHistoria odwiedzonych stronPoprzednia lekcjaKurs C++Następna lekcjaXIX. Dynamiczne zarządzanie pamięcią new i delete24.1. Ograniczanie maksymalnego rozmiaru danych odchodzi w zapomnienieDo tej pory pisząc programy w których organizowałeś dane, byłeś zmuszany do określania górnej granicy danych, jakie może pomieścić Twój program. Takie ograniczanie bardzo często nie jest jednak komfortowe i skuteczną alternatywą jest tu dynamiczne zarządzanie pamięcią.W języku C do przydzielania i zwalniania pamięci służyły głównie funkcje malloc() i free(). Korzystanie z nich było i jest nadal bardzo popularne, jednak w C++ zostały one zastąpione operatorami new i delete.24.2. Dynamiczne przydzielenie pamięciW języku C++ do przydzielania nowego bloku pamięci służy operator new. Jego składnia wygląda następująco:wskaznik1=new typ_zmiennej;wskaznik2=new typ_zmiennej[ilosc_elementow_danego_typu];Wskaźnik jak już dowiedziałeś się w rozdziale, który był temu poświęcony wskazuje na dane, a sam najczęściej zajmuje 4 bajty bez względu na to, na jakie dane wskazuje. Typ zmiennej informuje operator new, o rozmiarze pamięci jaka ma zostać przydzielona. Jeśli chcemy aby nowo przydzielony blok był tablicą to aktualną składnię uzupełniamy o dodatkowy parametr, w którym określamy ilość elementów tak samo jak robiliśmy to w przypadku tablic. Operator new na podstawie wszystkich podanych informacji przydzieli odpowiednią ilość pamięci tak, aby na pewno zmieściła się taka ilość danych o którą zażądałeś.Jeśli przydział pamięci powiódł się, to wartość zmiennej wskaźnik będzie różna od zera. Jeśli wartość wskaźnika będzie równa 0, to pamięć nie została przydzielona. Wartość 0 bardzo często jest zastępowana stałą NULL. Zalecane jest jednocześnie korzystanie ze stałej NULL, ponieważ standardy związane z wartością 0 mogą się kiedyś zmienić, a w związku z tym Twoje programy przestałyby działać. Powody, dla których pamięć nie mogła zostać przydzielona to:Rozmiar bloku pamięci, który chcesz zarezerwować jest zbyt duży;System nie posiada więcej zasobów pamięci i w związku z tym nie może Ci jej przydzielić.Dostęp do danych za pomocą wskaźników został już omówiony w rozdziale poświęconym wskaźnikom i nie będzie tu ponownie poruszany.24.3. Zwalnianie pamięci przydzielonej dynamicznieZwalnianie pamięci przydzielonej dynamicznie jest jeszcze prostsze od jej przydziału i służy do tego operator delete. Jeśli pamięć dla danych, na które wskazuje zmienna wskaznik została przydzielona bez parametru określającego ilość elementów w tablicy, to usuwana jest następującą składnią:delete wskaznik;Jeśli natomiast przydzieliliśmy pamięć z użyciem parametru określającego ilość elementów tablicy to musimy poinformować operator delete o tym, że wskaźnik wskazywał na tablicę rekordów. Aby to zrobić dopisujemy zaraz za operatorem nawiasy kwadratowe []. Nie podajemy jednak w nich rozmiaru tablicy, ponieważ operator ten sam ustala rozmiar bloku jaki został przydzielony, a następnie go usuwa z pamięci. Składnia tej operacji wygląda następująco:delete[] wskaznik_do_tablicy;24.4. Kopiowanie bloków pamięciJeśli będziemy chcieli przekopiować zawartość pamięci z jednego miejsca do drugiego możemy zrobić to conajmniej na dwa sposoby. Sposób pierwszy to wykorzystanie jakiejkolwiek pętli i kopiowanie danych bajt po bajcie. Przykład:for(int i=0;i<ilosc;i++) nowybufor[i]=starybufor[i];Problem jest w bardzo prosty sposób rozwiązany, jednak nie należy on do najwydajniejszych. Wydajniejszą metodą jest wykorzystanie funkcji, która służy do kopiowania bloków pamięci. Jej definicja wygląda następująco:void* memcpy(void* adres_docelowy,const void* adres_zrodlowy,size_t ilosc);Jako pierwszy parametr (adres_docelowy) podajemy adres do pamięci pod którym mają się znaleźć nowe dane. Drugi parametr (adres_zrodlowy) to miejsce z którego dane mają zostać pobrane i również określamy je za pomocą adresu. Trzecim, a zarazem ostatnim parametrem (ilosc) jest ilość bajtów, jaka ma zostać przekopiowana ze źródła do celu.Kopiując małe bloki pamięci różnicy w szybkości działania programu nie zaobserwujesz, jednak gdy przyjdzie Ci kopiować kilka MB danych różnice czasowe mogą być już bardzo odczuwalne.24.5. PrzykładPrzeanalizuj dokładnie działanie tego programu i poeksperymentuj z nim.#include<iostream>#include<conio.h>using namespace std;int main(){  int rozmiar=0;  int dlugosc=0;  char* tablica=NULL;  cout<<"Pusty wiersz konczy dzialanie programu."<<endl;  for(int i=0;i<40;i++)cout<<"-";  cout<<endl;  string tWiersz;  do  {    getline(cin,tWiersz);    if(tWiersz.length()>0)    {      tWiersz+="\r\n";//dopisanie nowego wiersza      if(dlugosc+tWiersz.length()+1>rozmiar)//potrzeba więcej pamięci niż jest dostępne      {        cout<<"Tworzy nowy blok pamieci!"<<endl;        int tNarzutDanych=20;//jeśli ustawisz 0 to rezerwacja będzie się odbywała za każdym razem        rozmiar=tWiersz.length()+dlugosc+1+tNarzutDanych;//nowy rozmiar bloku        char* tNoweDane=new char[rozmiar];//rezerwacja nowego bloku pamięci, który pomieści stare i nowe dane        if(tablica!=NULL) memcpy(tNoweDane,tablica,dlugosc);//jeśli stara tablica istnieje to skopiuj dane do nowej tablicy        memcpy(&tNoweDane[dlugosc],&tWiersz[0],tWiersz.length());//skopiuj dane do nowej tablicy w wyznaczone miejsce        if(tablica!=NULL) delete[] tablica;//zwolnij pamięć zajmowaną przez stare dane        tablica=tNoweDane;//nadaj nowy wskaźnik zmiennej tablica      }else      {//jest wystarczająca ilość pamięci nie wymagana rezerwacja        cout<<"Jest wystarczajaca ilosc miejsca!"<<endl;      }      memcpy(&tablica[dlugosc],&tWiersz[0],tWiersz.length());//skopiuj dane do tablicy w wyznaczone miejsce      dlugosc=tWiersz.length()+dlugosc;//zapisz długość tekstu      tablica[dlugosc]=0;//oznacz miejsce końca tekstu w tablicy    }  }while (tWiersz.length()!=0);  if(tablica!=NULL)  {    cout<<"Dane jakie wypisales to: "<<endl;    cout<<tablica<<endl;    delete[] tablica;  }else cout<<"Nie wpisales niczego!";  getch();  return(0);}Jeśli przeanalizowałeś przykład i go zrozumiałeś to zapewne stwierdziłeś, że taką funkcjonalność otrzymujesz korzystając z klasy std::string. Masz rację, jednak przykład ma na celu zademonstrowanie Tobie praktycznego, dynamicznego zarządzania pamięcią. Jeśli nie nauczysz się dynamicznie zarządzać pamięcią, możesz zapomnieć o realizowaniu jakiegokolwiek większego projektu z którego będzie płynął jakiś większy użytek, niż domowe wykorzystywanie własnych programów. Jest co prawda biblioteka szablonów, która umożliwia łatwe zarządzanie danymi jednak programista, który sam nie potrafi posługiwać się prawidłowo operatorami new i delete (lub funkcjami malloc() i free()) jest tylko jego imitacją, z której żaden pracodawca nie będzie miał pożytku.24.6. Informacje dodatkoweFunkcji malloc() nie można stosować zamiennie z operatorem new.Funkcji free() nie można stosować zamiennie z operatorem delete.Zamiana operatora new na funkcję malloc() może spowodować nieprawidłowe funkcjonowanie programu - operator new wykonuje czynności, które przy użyciu funkcji malloc() trzeba wywołać ręcznie.Jeśli dokonujesz zamiany funkcji malloc() na operator new, pamiętaj aby pozamieniać również funkcję free() na operator delete (lub delete[] w zależności od sytuacji).InformacjaNiniejsza lekcja została pierwotnie opracowana przez Piotra Szawdyńskiego. Autorem późniejszych modyfikacji jest już natomiast Dante, który jednocześnie dołożył swoją cegiełkę w rozwój kursu jak i serwisu.Poprzednia lekcjaKurs C++Następna lekcjaWszelkie prawa zastrzeżone. Autor: Piotr SzawdyńskiWszystkie teksty są chronione prawami autorskimi. Kopiowanie lub rozpowszechnianie treści bez wyraźnej zgody jego autora jest zabronione.PowrótHistoria odwiedzonych stronPanel LogowaniaLogin:Hasło:Zapamiętaj mnie!Zarejestruj sięOdzyskiwanie hasłaUżytkownikówObecnie aktywnych:6Zalogowanych:0Zarejestrowanych:4367Ostatnie 24h:501Non-cookie 24h:1505Wszystkich:264704Ostatnia Aktualizacja2010-11-23 00:46:20 (38 dni temu)Ostatnio aktywniHandy905 godzPiotr Szawdyński7 godzFletcher23 godzwiew25 godzPietrzuch25 godzmat250134 godzbooncki37 godzRaver59 godzWynajem Sopot - wakacjePokój 2 osobowy 130zł/doba;Lokalizacja: Sopothttp://sopotwynajem.pl O portaluArchiwumHistoriaIndeksRegulaminWyszukiwarkaLinkiRestauracja "ATOL" - Sopot© Wszelkie prawa zastrzeżone   2005-2010Czas wygenerowania strony: 0.084sAutor: Piotr Szawdyński

Wyszukiwarka

Podobne podstrony:
index9527
index971a
index9203
index9866
index9122
index9910
index90df
index96cc

więcej podobnych podstron