Pekare i C++ Pekare används mycket i C++. De är bra både för att de tillåter dynamisk minnesallokering och för att de är referenser. En pekarvariabel innehåller en adress till ett element, den pekar på ett element. Därför kallas också pekare för referenser. De refererar till ett element. Pekare måste tilldelas/allokeras minne, det görs inte automatiskt. Då man tilldelar/allokerar minne till en pekare sker det dynamiskt, d v s då programmet körs. Allt minne som är statiskt allokerat tilldelas programmet innan körningen av programmet startar. Man måste också frigöra minnet för pekaren när det inte behövs längre. Med att frigöra eller avallokera minne menas att man lämnar tillbaka minnet till systemet. För att komma åt det som pekaren pekar på måste man avreferera den. Exempel 1 Pekare int* x; char* y; struct s* t; Person* p; // x är en pekare till en integer // y är en pekare till en character // t är en pekare till en struct s // p är en pekare till en person En pekare tilldelas inte minne till det den ska peka på när den skapas, vilket innebär att man måste tilldela/allokera minne manuellt. Exempel på hur det går till finns nedan. Minnestilldelning (allokering) och frigörande (avallokering) av minne Exempel 2 Minnestilldelning Minnestilldelning görs med det reserverade ordet new samt den typ, och eventuell storlek om det handlar om en array, man vill allokera. int* pek; pek = new int; *pek = 7; int x = *pek; int* y; y = new int[30]; // enbart en intpekare utan minne // minne för att lagra ett heltal allokeras // tilldela värdet 7 till den intplats som pek // pekar på. // tilldela en vanlig intvariabel det värde som // pek pekar på. // enbart pekare utan minne // minne för att lagra en array med 30 heltal // allokeras. // y pekar nu på en array av heltal // y pekar på den första platsen i arrayen. for(int i=0; i<30; i++) y[i]=i; // y:s värden sätts till värden
//motsvarande positionen Person* person_pekare = new Person Nisse( Nisse Nilsson, {6,8,0,9,2,2,7,7,5,1}); //person_pekare pekar på ett personobjekt med namn Nisse Exempel 3 Frigörande av minne För att frigöra minne som tidigare allokerats används kommandot delete. delete pek; pek = 0; // Ta bort det utrymme som associeras med pek // Sätt pekaren till 0 (null) så den inte // refererar till något delete[] y; // Ta bort det utrymme som associeras med y. // Observera att man måste använda [] efter // delete för att ta bort en array. y = 0; delete person_pekare; person_pekare = 0; // Ta bort det utrymme (objekt) som // associeras med person_pekare.
Fler exempel Exempel 4 Olika pekaroperationer typedef int* ptrtype; ptrtype p, ; p int x; x p = &x p x eller *p *p = 6; 6 p x eller *p p = new int; 6 x *p=7 7 6 x = p; 7 6 p *p eller * x = new int; 7 6 x *=8; 8 *
p = 0; 7 6 p x 8 * delete ; 7 6 p x = 0;
Exempel 5 Ytterligare exempel på pekare typedef int* ptrtype; 1. ptrtype p, ; p 2. p = new int; 3. *p = 1; 1 4. = new int; 1 * 5. * = 2; 1 cout << *p << << * << endl; ger utskriften: 1 2 2 * 6. *p = * + 3 ; 5 2 *
7. p = ; p 5 cout << *p << << * << endl; ger utskriften: 2 2 2 *p eller * 8. *p = 7; p 5 cout << *p << << * << endl; ger utskriften: 7 7 7 *p eller * 9. p = new int; 5 7 * 10. delete p; p = 0; = 0; p 5 7
Faror med pekare int* x, y; // ger en intpekare x och en int, y. int* x, *y; // ger två intpekare, x och y. Se upp med asterisken (*) eftersom den hör ihop med variabeln och inte med typen. OBS! Ta för vana att aldrig deklarera mer än en pekare på varje rad, då blir detta inget problem. Man får inte ta bort minne för en pekare som inte tilldelats något minne. Man får inte tilldela en pekare ett värde om den inte tilldelats något minne. char* char_pekare; *char_pekare = f ; delete char_pekare; //NEJ, NEJ, NEJ!!!!! //NEJ, NEJ, NEJ!!!!! double* double_pekare = new double; *double_pekare = 3.1415; //OK, det finns minne allokerat. delete double_pekare ; //OK, här finns det minne att ta bort. Tänk på att asterisken (*) används med två olika innebörder. Dels för att deklarera en pekare och dels för att komma åt det som pekaren pekar på. Sätt alltid pekaren till 0 (null) om den inte refererar till något vettigt. Det är lätt att glömma detta. int* int_pekare = new int; *int_pekare = 55; delete int_pekare; int_pekare = 0; // Sätt pekaren till 0 (null), den refererar // inte längre till något vettigt. Tänk på att alltid använda delete[]då du tar bort minne som allokerats som en array. int* array = new int[50]; delete[] array; array = 0;
Repetition av nyckelbegrepp int* p allokerar en pekarvariabel p med ett odefinierat värde. p kan peka till ett heltal. p = new int; allokerar en ny minnescell för heltal dynamiskt. p sätts att peka på denna minnescell. new är en operator som returnerar adressen till det allokerade minesutrymmet. Uttrycket *p refererar till den minnescell som p pekar på. Om pekarvariabeln p har värdet 0 (null) pekar den inte på någonting. delete p; återlämnar minnescellen som p pekar på till systemet. Pekaren p tas dock inte bort varför p måste sättas till 0 (null) efter operationen för att inte peka på en återlämnad minnescell. p = 0; Asterisken (*) används till två saker. Dels för att skapa pekaren och dels för att referera till den minnescell som pekaren pekar på.