TDDC76 - Programmering och Datastrukturer Pekare och Listor Eric Elfving Institutionen för datavetenskap
1 / 21 Översikt Internminne Pekare Dynamiska datastrukturer (Enkellänkade) listor
2 / 21 Internminne - RAM Datorns internminne (RAM, random access memory) består av en ordnad sekvens bitar Vi kan normalt sett adressera (komma åt) en byte i taget (8 bitar)
3 / 21 Minne
4 / 21 Minne Vad händer i minnet? int x {3421}; x: int 3421
5 / 21 Variabler En variabel har alltid: Ett namn En datatyp Ett värde En adress
6 / 21 Pekare En pekare lagrar en adress till en given position i minnet Deklareras med en asterisk (*) int * ip;
7 / 21 Pekare Man kan ta fram adressen till en variabel med adressoperatorn (&) int x {3421}; int * ip {&x}; int x: ip: 3421
8 / 21 Pekare För att komma åt det värde en pekare pekar på används avrefereringsoperatorn (*) #include <iostream> using namespace std; int main() { int x {3421}; int *ip {&x}; cout << ip << endl; cout << *ip << endl; return 0; } 14 3421 Vi får bara avreferera pekare som pekar på adresser som vårt program äger
9 / 21 Pekare Pekare används oftast för att skapa dynamiskt minne Vi allokerar nytt minne med new-operatorn Vi kan endast nå det nya utrymmet med hjälp av pekaren int* ip; ip = new int; *ip = 5123; int * ip {new int{5123}};
10 / 21 Pekare Minnesläcka Om vi redan pekar på en minnesadress och ber om nytt utrymme tappar vi bort det vi pekade på. Detta kallas minnesläcka, ett av de vanligaste felen när vi jobbar med pekare Vi äger fortfarande utrymmet, men har inget sätt att nå det int* ip {new int{44}}; ip = new int{123}; int 44 int ip: 123
11 / 21 Pekare Om vi vill lämna tillbaka minne till operativsystemet gör vi det med delete-operatorn int *ip {new int{345}}; int ip: 345 delete ip; int ip: 345 OBS, delete ändrar inte på pekarens värde!
12 / 21 Pekare Värdet nullptr betyder inget värde för pekare 1 int * ip{}; // ip sätts till nullptr 2 ip = new int{}; // det nya heltalet får värdet 0 3 delete ip; 4 ip = nullptr; kodrad: 1 2 3 4 Minnet: int ip: ip: 0 int ip: 0 ip:
13 / 21 Pekare void f(int *p) { delete p; p = new int{2}; } int main() { int *ptr {new int{12}}; f(ptr); cout << *ptr << endl; delete ptr; } Vad händer?
14 / 21 Pekare Precis som vanligt måste vi ta emot referenser om vi vill ändra på värden: void f(int *& p) { delete p; p = new int{2}; } int main() { int *ptr {new int{12}}; f(ptr); cout << *ptr << endl; delete ptr; }
15 / 21 Alias Om man tycker det är jobbigt med alla asterisker kan man skapa ett nytt namn för en typ med aliasdefinition Skrivs på formen using NAMN = TYPBESKRIVNING; using int_ptr = int *; void f(int_ptr & p); int main() { int_ptr ptr { new int{4} }; delete ptr; }
16 / 21 Pekare till poster För att komma åt fälten i poster kan man använda sig av medlemsåtkomstoperatorn (->) struct Book { string title; string author; int pages; }; Book *bp { new Book }; bp->title = "C++ Primer"; Man kan använda avreferering också, men då krävs parenteser cout << (*bp).title << endl;
17 / 21 Dynamiska datastrukturer En dynamisk datastruktur kan ändra storlek under programkörningen Vi har redan använt en dynamisk datastruktur, string Det finns många fler inbyggda i std, exempelvis vector som kan lagra flera värden av en viss typ.
18 / 21 Dynamiska datastrukturer Tänk er att vi vill stoppa in ett värde sorterat i en vector. Då behöver vi: Hitta rätt position 7 0 4 12 17 0 1 2 3
18 / 21 Dynamiska datastrukturer Tänk er att vi vill stoppa in ett värde sorterat i en vector. Då behöver vi: Hitta rätt position Utöka storleken 7 0 4 12 17? 0 1 2 3 4
18 / 21 Dynamiska datastrukturer Tänk er att vi vill stoppa in ett värde sorterat i en vector. Då behöver vi: Hitta rätt position Utöka storleken Flytta alla värden som ligger efter hittad position 7 0 4 12 17? 0 1 2 3 4
18 / 21 Dynamiska datastrukturer Tänk er att vi vill stoppa in ett värde sorterat i en vector. Då behöver vi: Hitta rätt position Utöka storleken Flytta alla värden som ligger efter hittad position 7 0 4 12 17 17 0 1 2 3 4
18 / 21 Dynamiska datastrukturer Tänk er att vi vill stoppa in ett värde sorterat i en vector. Då behöver vi: Hitta rätt position Utöka storleken Flytta alla värden som ligger efter hittad position Stoppa in värdet 7 0 4 12 12 17 0 1 2 3 4
18 / 21 Dynamiska datastrukturer Tänk er att vi vill stoppa in ett värde sorterat i en vector. Då behöver vi: Hitta rätt position Utöka storleken Flytta alla värden som ligger efter hittad position Stoppa in värdet 7 0 4 7 12 17 0 1 2 3 4
19 / 21 Enkellänkade listor En enkellänkad lista består av noder. En nod är en post som innehåller två saker, ett värde av någon datatyp samt en pekare till nästa nod i listan. Detta gör en pekare till en nod till en lista. Tom lista (eller slutet av listan) markeras med pekarvärdet nullptr. 3 7 9
20 / 21 Enkellänkade listor 3 7 9
21 / 21 Enkellänkade listor Deklaration av en listtyp: struct List_Node { int data; List_Node * next; }; Alternativ lösning med alias: struct List_Node; using List = List_Node *; struct List_Node { int data; List next; };
Eric Elfving Institutionen för datavetenskap www.liu.se