wyklad nr 9 7 xii


POLITECHNIKA WARSZAWSKA
POLITECHNIKA WARSZAWSKA
Instytut Automatyki i Robotyki
Instytut Automatyki i Robotyki
ZASADY PROGRAMOWANIA KOMPUTERÓW
ZASADY PROGRAMOWANIA KOMPUTERÓW
Język programowania: C/C++
Język programowania: C/C++
Środowisko programistyczne: C++Builder 6
Środowisko programistyczne: C++Builder 6
Wykład 9 . Wskazniki i zmienne dynamiczne.
Wykład 9 . Wskazniki i zmienne dynamiczne.
Alokacja statyczna
Alokacja statyczna
Zmienne statyczne globalne - tworzone są w momencie uruchomienia
programu na skutek zawartych w nim deklaracji zmiennych globalnych i
istnieją aż do zakończenia jego wykonywania (zajmują więc cały czas
pamięć).
Zmienne statyczne lokalne - tworzone są w momencie wywołania funkcji
na skutek zawartych w niej deklaracji zmiennych lokalnych i istnieją aż do
wyjścia z funkcji (zajmują więc przez ten czas pamięć).
Przydział pamięci na zmienne statyczne jest to tzw. alokacja statyczna,
która odbywa się automatycznie (bez udziału programisty) w obszarze
pamięci operacyjnej, zwanym stosem (ang. stack) programu. Stos ma
stały rozmiar (rzędu 1MB) i łatwo może ulec przepełnieniu (stack
overflow), np. w przypadku zbyt dużych tablic lub zle napisanej rekurencji.
Alokacja dynamiczna
Alokacja dynamiczna
Zmienne dynamiczne - tworzone są podczas wykonywania programu za
pomocą odpowiedniej instrukcji (new) i istnieją aż do momentu
skasowania, za pomocą przeznaczonej do tego instrukcji (delete).
Zajmują więc pamięć tylko do momentu skasowania. Potem tę samą
pamięć można w tym samym lub innym programie wykorzystać na inne
zmienne dynamiczne (które trzeba od nowa utworzyć).
Przydział pamięci na zmienne dynamiczne, czyli tzw. alokacja
dynamiczna, odbywa się w trakcie pracy programu na żądanie
programisty (instrukcją new) w obszarze pamięci zwanym stertą (ang.
heap). Na stertę wykorzystywana jest cała dostępna pamięć wirtualna
komputera (pamięć RAM oraz pamięć wymiany na dysku twardym).
Może to oznaczać do 2GB, a nawet 3GB pamięci (przestrzeń adresowa w
systemie 32-bitowym to 2^32, czyli 4GB pamięci, z czego 1- 2GB zajmuje
jądro systemu operacyjnego).
Alokacja dynamiczna c.d.
Alokacja dynamiczna c.d.
Przydzieloną pamięć dynamiczną należy zwolnić odpowiednimi
instrukcjami (delete), czyli  posprzątać po sobie . Jeśli się tego nie zrobi,
pamięć nie będzie (w ogólnym przypadku) zwolniona aż do zamknięcia
systemu; kolejne uruchomienia takiego programu powodują wówczas
ciągłe zmniejszanie się dostępnej pamięci (tzw. wyciek pamięci).
Po co stosujemy zmienne dynamiczne ?
" umożliwiają tworzenie struktur dynamicznych, o nie znanej z góry
wielkości (listy, drzewa), bez niepotrzebnego rezerwowania na zapas
pamięci statycznej;
" umożliwiają tworzenie bardzo dużych tablic;
" można je w każdej chwili podczas działania programu usunąć z pamięci
i na zwolnionym miejscu utworzyć nową zmienną dynamiczną - w tym
samym lub innym programie. Ułatwiają więc równoległą pracę wielu
programów w systemie operacyjnym.
Wskazniki i zmienne wskazywane
Wskazniki i zmienne wskazywane
Do zmiennych statycznych z reguły odwołujemy się poprzez ich nazwy
(identyfikatory):
a = 1; // podstaw 1 pod zmienną o nazwie a
Do zmiennych dynamicznych z reguły odwołujemy się poprzez ich adresy
(wskazniki), używając gwiazdki * stojącej po ich lewej stronie:
*w = 1; // podstaw 1 pod zmienną wskazywaną przez w
Zatem:
w - jest tu adresem, czyli wskaznikiem i musi być typu wskaznikowego;
jest to zmienna wskaznikowa, będąca zwykłą zmienną statyczną (ma swoją
nazwę, podobnie jak inne zmienne statyczne, i miejsce w pamięci zajęte przez cały czas
wykonywania programu).
*w - jest zmienną dynamiczną, wskazywaną przez adres w i może być
dowolnego typu (typ ten podaje się przy deklaracji wskaznika). Dlatego
zmienne dynamiczne nazywamy inaczej zmiennymi wskazywanymi.
Wskazniki i zmienne wskazywane c.d.
Wskazniki i zmienne wskazywane c.d.
Nazwy wskazników mogą być zupełnie dowolne, tak jak dowolne mogą
być nazwy wszystkich innych zmiennych:
*a = "co to?"; // pod zmienną wskazywaną przez a podstaw napis "co to?"
*wsk_i = 20; // pod zmienną wskazywaną przez wsk_i podstaw liczbę 20
*adres = 3.8; // pod zmienną wskazywaną przez adres podstaw wartość 3.8
cout << *adres << *a; // wydrukuj zmienną wskazywaną przez adres
// i zmienną wskazywaną przez a
Na zmiennych dynamicznych można
wykonywać te same operacje, co na
zmiennych statycznych, tylko należy się do
nich inaczej odwoływać - poprzez wskaznik,
czyli używając operatora * do wyłuskania
wartości tych zmiennych
Wskazniki i zmienne wskazywane - przykłady
Wskazniki i zmienne wskazywane - przykłady
Zmienne dynamiczne mogą różnych typów, tak jak wszystkie inne
zmienne. Zmienne dynamiczne mogą być dowolnie rozrzucone w
pamięci komputera:
Wskaznik przechowuje adres początku obszaru pamięci przydzielonego
na zapamiętanie zmiennej dynamicznej.
Deklaracja wskaznika
Deklaracja wskaznika
Żeby skorzystać ze zmiennej dynamicznej, musimy najpierw
zadeklarować wskaznik do tej zmiennej, podając typ zmiennej
wskazywanej. Piszemy więc tak:
int *wsk_i;
co należy czytać:
zmienna wsk_i jest wskaznikiem do zmiennej typu int.
Deklaracja wskaznika
typ zmiennej wskazywanej *nazwa wskaznika;
Jeśli jednak wskaznik wskazuje rekord, to wcześniej trzeba ten typ
rekordowy, czyli strukturę, zdefiniować.
Przykłady deklarowania i używania wskazników
Przykłady deklarowania i używania wskazników
struct Sam {
string marka;
int rocznik;
double cena;
};
...
int main( ) {
...
int *wsk_i;
string *a;
Zmienna ad_auta jest wskaznikiem
Sam *ad_auta;
do zmiennej typu Sam:
Tak nie wolno,
string *wsk_wek;
bo kropka jest
...
*ad_auta . cena = 35000;
silniejsza od
*wsk_i = 20;
gwiazdki
*a = "co to?";
(*ad_auta) . cena = 35000;
(*ad_auta) . cena = 35000;
*wsk_wek = "Pawel";
równoważne
wersja krótsza w zapisie:
*(wsk_wek+1) = "Maciej";
ad_auta -> cena = 35000;
...
return 0;
wskaznikowy sposób działania na tablicach (o tym dalej)
}
Tworzenie zmiennych dynamicznych
Tworzenie zmiennych dynamicznych
Adres (czyli wskaznik) zmiennej wskazywanej otrzymujemy w trakcie
działania programu w wyniku wykonania instrukcji
Tworzenie zmiennej dynamicznej
nazwa wskaznika = new typ zmiennej wskazywanej ;
Jak to działa:
Operator new przydziela pamięć na zmienną dynamiczną typu podanego i
adres tej zmiennej podstawia pod wskaznik o podanej nazwie. Jeżeli
alokacja (przydział pamięci) się nie powiedzie, np. pamięci już nie wystarczy,
pod wskaznik wstawi adres pusty (NULL).
w = new int ;
// przydziel pamięć na zmienną typu int i adres zapamiętaj jako wskaznik w.
ad_auta = new Sam ;
// przydziel pamięć na zmienną typu Sam i adres zapamiętaj jako ad_auta
Usuwanie zmiennych dynamicznych
Usuwanie zmiennych dynamicznych
Adres (czyli wskaznik) zmiennej wskazywanej kasujemy w trakcie
działania programu w wyniku wykonania instrukcji
Usuwanie zmiennej dynamicznej
delete nazwa wskaznika ;
Jak to działa:
Operator delete zwalnia pamięć zarezerwowaną na zmienną dynamiczną
pod adresem o podanej nazwie i kasuje ten wskaznik (potem nie można się
już do niego odwoływać).
delete w;
delete ad_auta;
" Nie wolno używać delete do zwalniania pamięci nie przydzielonej przez
new (np. określonej przez wskaznik do zmiennej statycznej)
" Nie wolno dwukrotnie zwalniać tego samego obszaru pamięci
" Można zastosować delete do wskaznika pustego (nic się nie stanie)
Przykłady tworzenia i usuwania zmiennych dynamicznych
Przykłady tworzenia i usuwania zmiennych dynamicznych
int *w;
// deklaracja wskaznika do zmiennej integer;
w = new int;
// przydzielenie pamięci zmiennej typu int wskazywanej przez w
*w = 20;
// podstawienie liczby 20 pod adres w
cout << "Wartosc wskazywana powiekszona o 5 " << (*w)+5 << endl;
// dodanie liczby 5 do wartości wskazywanej przez w
delete w;
// zwolnienie pamięci pod adresem w i skasowanie tego adresu
Operator * i &
Operator * i &
int *w;
int* w; Zapisy równoważne:
int * w; w jest wskaznikiem do zmiennej typu int
int *ad1, *ad2, *ad3;
tak definiujemy kilka wskazników
int a ;
Jak interpretować wyrażenia (przy powyższych definicjach zmiennych):
*w
wez to, co jest pod adresem w
znajdz wskaznik do zmiennej a (jej adres)
& a
w
*w
w - wskaznik (zmienna statyczna)
*w - zmienna dynamiczna (wskazywana przez w)
a - zmienna statyczna
& a
a
& a - wskaznik (zmienna statyczna)
Operator & i nietypowe odwołania
Operator & i nietypowe odwołania
Do zmiennych statycznych możemy się dostać za pomocą adresów,
używając operatora &:
int *w; // w jest wskaznikiem do zmiennej typu int
int a = 1; // podstaw 1 pod zmienną o nazwie a
w = & a ; // podstaw pod w wskaznik do zmiennej a
// zatem od tej pory zamiast a możemy pisać *w (tylko po co?)
cout << *w; // wydrukuj to, co jest pod adresem w (czyli 1)
Do zmiennych dynamicznych można się dostać za pomocą nazwy,
używając operatora &:
int *w; // w jest wskaznikiem do zmiennej typu int
int *w = &b; // zaś b jest nazwą zmiennej dynamicznej typu int
// wskazywanej przez w (bo adres zmiennej b = wskaznikowi w)
Dynamiczna rezerwacja tablic jednowymiarowych
Dynamiczna rezerwacja tablic jednowymiarowych
int main( ) { // zarezerwujemy tablicę T typu int
int *T ; // T jest wskaznikiem do pierwszego elementu tablicy
int n;
cout << "ile elementow w tablicy ? " << endl;
cin >> n;
T=new int [n]; // rezerwujemy pamięć dla n elementów tablicy typu int
// i adres pierwszego z nich zapamiętujemy jako T
...
for (int i=0; i> T[ i ]; // zwykłe działania na tablicy
...
delete [ ] T; // tak zwalniamy pamięć przydzieloną na tablicę
...
Zamiast :
...
Tak nie wolno działać na
return 0;
int * T ;
tablicach statycznych:
}
T=new int [n];
int n;
cin >> n; można napisać od razu:
int T [n] ;
int * T = new int [n];
Tablice w notacji wskaznikowej
Tablice w notacji wskaznikowej
Wszystkie elementy tablicy są umieszczone w ciągłym obszarze
pamięci jeden za drugim:
Nazwa tablicy użyta w wyrażeniach jest adresem początkowego elementu
tablicy (uwaga: wyjątkiem jest funkcja sizeof, która odnosi się do całej tablicy)
wskazniki
zmienna przechowująca
adres
Do elementów tablic rezerwowanych dynamicznie możemy się odwoływać
w sposób tradycyjny, zgodnie z notacją tablicową.
Ale notacja wskaznikowa z natury rzeczy umożliwia szybszy, bezpośredni
dostęp do elementów tablicy, nie wymagający wyznaczania wartości
indeksów, a tylko dodawania liczb naturalnych do adresu.


Wyszukiwarka

Podobne podstrony:
wyklad nr  xii
wyklad nr ! xii
ZARZĄDZANIE WARTOŚCIĄ PRZEDSIĘBIORSTWA Z DNIA 26 MARZEC 2011 WYKŁAD NR 3
Zarzadzanie strategiczne wyklad nr 2
wyklad nr 2 PK
Wykład nr 6 Decyzja
wyklad nr 4 & x
SS wyklad nr 6 ppt
Sem 4 Wykład nr 9 Interakcje 2013
AUDYT WEWNĘTRZNY Z DNIA 26 LUTY 2011 WYKŁAD NR 1
WYKŁAD NR 5 HYDRAULIKA i HYDROLOGIA (PDF)
wykład nr 6
Wyklad nr 8
WYKŁAD NR 3
Wykład nr 3
OP wyklad nr 4
ET DI2 ObwodySygnaly2 wyklad nr 9 10 czworniki aktywne
Prezentacja Wykład nr 5

więcej podobnych podstron