larkid.pages.dev









Vad händer om man tar pekare 5

Pekarvariabler samt dynamisk minnesallokering

Kapitel 5.4 (ej 5.4.8) inom C++ Direkt

Användning från pekare ger en effektivt sätt för att hantera datorns minne samt objekt. flera uppfattar pekare liksom svåra, samt detta existerar dem möjligen även. Utan tvekan existerar detta inom samtliga fall enkelt för att utföra fel tillsammans med pekare, fel liksom ej upptäcks från kompilatorn, dock ger svårbegripliga programkrascher.

Därför existerar detta viktigt för att man dels besitter ett god primär medvetande till datorns minne samt pekarna mot detta, dels ständigt tänker igenom samtliga pekaroperationer noga samt tar varenda situationer likt förmå uppkomma tillsammans inom beräkningen.

Måste man nyttja pekare inom C++? Ja, detta existerar tyvärr sålunda för att pekare - samt därmed dynamisk minneshantering - existerar nödvändigt inom C++: dels kunna man ej erhålla polymorfi (momentet Polymorfi inom lektionen Arv ) utan pekare, dels används pekare samt pekarliknande term genomgående inom standardbiblioteket ( lektionen Standardbiblioteket).

Minnen, celler, adresser samt pekare

Låt oss börja tillsammans med för att ställa upp ett foto från datorns minne: enstaka utdragen rad, ett array, från minnesceller likt kunna innehålla enstaka int, char, double alternativt någon ytterligare datatyp alternativt objekt. Detta existerar ej riktigt precis. Egentligen innehåller varenda fängelse ett byte, samt flera byte bygger sedan upp enstaka datatyp.

dock såsom oss skall titta behöver man ej bry sig ifall sådant.

Varje minnescell besitter enstaka unik adress (här framträda ett bit från minnet såsom börjar vid plats 0, inom verkligheten ligger variablerna inom en schema vid betydligt högre adresser dock principen existerar densamma - oss är kapabel t.ex.

tänka oss för att addera 10000000 mot dem adresser såsom anges inom detta moment):

Adress:

00

01

02

03

04

05

06

07

08

09

10

11

12

13

14

Celler:

123

132

131

12

0

45

45

11

19

0

0

0

100

1

47


Innan vårt schema börjar exekvera ligger detta skräp (=vad såsom helst) inom minnet.

Vad sker för tillfället ifall oss inom vårt schema deklarerar samt initierar enstaka integer myint? enstaka fängelse inom minnet allokeras då på grund av enstaka integer, samt kompilatorn associerar adressen mot denna minnescell tillsammans med symbolen myint.

Detta för att checka av om du fortfarande behöver ta din medicin eller så att de inte krockar med varandra, om du tar flera läkemedel

för att cellen allokeras betyder för att systemet ser mot för att ej notera någonting vid den adressen förutom då symbolen myint tilldelas en värde. angående oss önskar känna till själva adressen på grund av den minnescell liksom existerar associerad tillsammans myint, är kapabel oss nyttja den unära (=som opererar vid en argument) &-operatorn.

int myint;// denna plats allokeras enstaka int-cell, samt adressen

// associeras tillsammans med symbolen myint

cout << &myint;// på denna plats skrivs adressen mot minnescellen ut

myint=5;// oss fyller år cellen tillsammans värdet 5

cout << myint;// på denna plats skrivs värdet från myint (d.v.s. 5)

Om oss antar för att nästa lediga minnesadress existerar 0 kommer minnet efter dessa deklarationer för att titta ut därför på denna plats (fet stil anger både på denna plats samt senare för att denna minnescell besitter allokerats):

Adress:

00

01

02

03

04

05

06

07

08

09

10

11

12

13

14

Celler:

5

132

131

12

0

45

45

11

19

0

0

0

100

1

47


samt utskriften blir:

0

5

Vad existerar enstaka pekare?

·         en plats mot ett minnescell

·         inte en vanligt heltal

·         inte identisk sak liksom ett minnescell

·         oanvändbar tills man besitter satt den för att peka vid något - ett deklaration från typen int *pek sägar bara för att pekkan peka vid ett int

·         När den pekar vid något, förmå man nyttja den unära*-operatorn till för att ett fåtal detta vilket pekaren pekar vid.

Uttrycket "*myptr = 6" existerar - angående myptr pekar vid myint - identisk sak liksom "myint = 6". Alltså existerar *myptr samt myint identisk sak (se kodexemplet nedan)

·         För för att sätta enstaka pekare för att peka vid något, kunna man nyttja &-operatorn (också kallad adressoperatorn).

Men det finns vissa undantag

Blanda ej ihop denna operator tillsammans med referensoperatorn likt ser likadan ut.

Litet kodexempel

int myint;// på denna plats allokeras ett fängelse vilket innehåller ett int.

// myint associeras tillsammans med adressen

int* myptr;// denna plats deklareras ett pekare mot integer.

// Den pekar ej vid något särskilt

myptr = &myint; // för tillfället pekar myptr vid variabeln myint

myint=5;// oss fyller år cellen tillsammans med värdet 5

*myptr=6;// oss fyller år cellen tillsammans med värdet 6

cout << myint;// Utskriften blir '6', ej '5'

cout << myptr;// Adressen mot minnescellen skrivs ut

// (jämför förra exemplet)

cout << *myptr; // Innehållet inom cellen skrivs ut, dvs '6'

Om man ritar upp modellen från datorns minne, kunna detta alltså titta ut liksom nedan.

myptr pekar vid adressen 00, liksom äger blivit reserverad för att innehålla myint. Dessutom besitter ställe reserverats till variabeln myptr vilket ligger strax efter myint inom minnet (vi antar för att ett pekare samt enstaka int tar lika massiv plats). oss kunna alltså vilket inom exemplet ovan anlända åt innehållet inom cellen vid numeriskt värde sätt: genom myint samt genom *myptr.

Adress:

00

01

02

03

04

05

06

07

08

09

10

11

12

13

14

Celler:

6

00

131

12

0

45

45

11

19

0

0

0

100

1

47

Endast minnescellerna 00 (värdet 6 vilket existerar myints värde) samt 01 (värdet 00 likt existerar myptrs värde, d.v.s.

adressen förmyint) besitter fått värden, resten från minnet innehåller ännu skräp.

Pekare måste initieras innan dem används

Observera för att detta ej existerar oss vilket bestämmer vilken plats oss får notera i! oss kunna bara ta emot dem minnesadresser likt systemet ger oss, eftersom detta bara existerar dem såsom äger blivit allokerade.

Endast då vet oss

1.      Att oss ej skriver inom någon ytterligare information

2.      Att detta oss skriver ej kommer för att tecknas ovan tillsammans något annat.

Man får alltså absolut inte utföra vilket inom exemplet nedan:

int *myptr; // på denna plats deklareras ett pekare

myptr = 20; // Pekaren sätts för att peka vid adressen 20.

// vad vilket finns var, vet oss ej.

*myptr = 5; // oss skriver någonting vid adressen 20. FEL! FEL!

Felet på denna plats ovan kommer helt säkert för att orsaka svåra fel, möjligen programkrasch (om oss besitter tur), samt visar hur viktigt detta existerar för att ej blanda samman pekare mot enstaka fängelse tillsammans själva cellen.

angående man bara kunde sätta pekare för att peka vid redan deklarerade variabler liksom inom exemplet ovan, skulle dem ej artikel således användbara. oss skall snart titta hur man egen kunna allokera minne inom datorn.

Pekare liksom pekar vid ingenting

Helst bör alltså pekare placeras för att peka vid något redan då dem deklareras.

är kapabel man ej utföra detta ska dem ges värdet 0:

int* ipekaren = 0;

double* dpekare = 0;

En pekare liksom innehåller värdet 0 kallas ett tom pekare alternativt nollpekare (null pointer). Egentligen får man ej tilldela heltal mot pekare utan typomvandling, dock detta konstanta värdet 0 existerar en undantag. vid sålunda sätt äger pekarna en definierar värde även angående dem ej pekar vid något!

Anledningen mot för att detta existerar således viktigt existerar för att man förmå testa angående enstaka pekare existerar 0 innan man använder den:

void enFunktion( int *p )

{

if (p != 0) { /* OK, oss kunna nyttja detta p pekar på! */ }

else return; // nollpekare, oss kunna ej utföra något vettigt

}

Pekare existerar typkontrollerade

Observera för att ett pekare kunna peka endast vid variabler från den typ till vilken den deklarerats: datatyperna "pekare mot double" samt "pekare mot int" existerar skilda typer samt variabler från dem båda typerna är kapabel ej tilldelas varandra:

int i;

double *dpek = &i // förbjudet!

Detta existerar naturligt eftersom representationen från double inom datorn helt skiljer sig ifrån representationen från int.


  • vad  sker  angående man tar pekare 5

  • Deklaration från pekare

    Antag nästa deklaration:

    int* a,b;

    int *c,*d;

    Observera för att *-tecknet hör mot variabeln, ej typen, d.v.s. inom deklarationen ovan blir b enstaka vanlig int, inte enstaka pekare mot enstaka int. Man är kapabel placeras *-tecknet fanns såsom helst mellan typen samt varibelnamnet.

    Denna kod deklarerar fem pekare:

    int* pek1;

    int * pek2;

    int *pek3;

    int *pek4;

    int*pek5;

    Använd gärna typedef

    Detta för att * måste anges till varenda pekarvariabel brukar ge upphov mot fel.För för att minska felrisken är kapabel man utnyttja sig från ett språkkonstruktion likt heter typedef.

    Om man äger enstaka komplicerad typ är kapabel man nyttja typedef till för att ge typen en namn. Man kunna sedan nyttja detta namn inom fortsättningen, inom stället till för att ange den komplicerade typen.

    Antag t.ex. för att oss önskar jobba tillsammans med variabler från typerna "pekare mot int", dock önskar undvika fel från typen ovan.

    oss kunna då " ge nästa deklaration:

    typedef int *intPointer;

    En typedef-deklaration äger noggrann identisk form eller gestalt vilket ett vanlig variabeldeklaration. Den enda skillnaden existerar för att termen typedef kommer inledningsvis. inom enstaka typedef-deklaration deklareras ej enstaka variabel, utan en typnamn.

    oss äger alltså på denna plats deklarerat namnet intPointer. Detta namn förmå sedan användas liksom en enkelt typnamn vid varenda ställen var man förmå ange enstaka typ. oss förmå t.ex. deklarera variablerna ip1 samt ip2:

    intPointer ip1, ip2;

    Här blir både ip1 samt ip2 pekare mot int. Användningen från typedef skapar alltså ej någon fräsch typ; oss äger bara fått en enklare sätt för att deklarera pekare mot int.

    Sammanfattning således långt

    Pekare är:

    ·         En pekare existerar ett variabel likt äger enstaka minnesadress liksom värde.

    ·         En pekarvariabel pekar vid enstaka viss sorts variabel.

    ·         En pekare är kapabel peka rakt ut inom tomma luften!

    ·         En pekare måste alltså initieras innan den används.

    ·         En pekare deklareras datatyp *namn;

    ·         Observera för att * hör mot variabeln, ej typen.

    Om * samt &

    I C++ kod

    Förklaring

    Exempel

    * (i deklaration)

    pekare mot

    int *a;

    * (i kod)

    det liksom finns där,    
    värdet

    *a

    & (i kod före variabel)

    adressen mot

    int b=5; a=&b;

    & (mellan datatyp samt variabel)    

    referensen mot

    void d(int &b)

    Arrayer samt pekare existerar identisk sak!

    Något man måste uppleva mot liksom C++-programmerare existerar sambandet mellan arrayer samt pekare.

    Några exempel: const int a = 5; // en vanlig variabel

    ifall oss önskar deklarera ett array från ints, säga 6 element utdragen, skriver oss liksom vän

    int myArr[6];

    Hur ser vår datorminnesmodell ut för tillfället (vi antar för att varenda integer tar upp ett minnescell samt för att arrayen allokeras vid minnesadresserna ifrån samt tillsammans med 02 mot samt tillsammans med 07.

    plats 00 samt 01 besitter oss ju redan tagit upp inom föregående avsnitt)?

    Adress:

    00

    01

    02

    03

    04

    05

    06

    07

    08

    09

    10

    11

    12

    13

    14

    Celler:

    5

    00

    131

    12

    0

    45

    45

    11

    19

    0

    0

    0

    100

    1

    47

    Pekararitmetik

    Vi ser för att ytterligare sex minnesceller besitter blivit allokerade.

    Adressen mot den inledande associeras tillsammans med symbolen myArr[0], den andra tillsammans myArr[1], osv. Antag för tillfället för att oss deklarerar ett int-pekare samt sätter den för att peka vid detta inledande elementet. förmå oss då nyttja den på grund av för att komma åt dem andra elementen inom arrayen? Ja, genom för att stega upp pekaren!

    int myArr[6];

    int* myptr;

    myptr = &myArr[0]; // för tillfället pekar myptr vid 1:a elementet inom myArr

    myptr++; // för tillfället pekar myptr vid andra elementet

    myptr++; // Pekar vid tredjeplats elementet

    Efter dessa operationer ser minnet ut således här:

    Adress:

    00

    01

    02

    03

    04

    05

    06

    07

    08

    09

    10

    11

    12

    13

    14

    Celler:

    5

    00

    131

    12

    9999

    45

    45

    11

    04

    0

    0

    0

    100

    1

    47

    Vi ser för att pekarvariabeln myptr placerats inom nästa lediga minnescell (08) samt för att detta tredjeplats elementet (myArr[2] - såsom efter operationerna ovan existerar identisk sak såsom *myptr) fått värdet 9999.

    Övriga element inom arrayen existerar oinitierade.

    Från detta ovanstående inser man idag för att ett pekare existerar mer än bara en heltal. Genom för att nyttja ++-operatorn, stegar oss oss fram ett int inom taget, utan för att bry oss angående hur flera bytes enstaka int tar upp. ifall oss ägde vanliga heltal, skulle oss behöva tänka vid sådant.

    detta existerar bl. a. därför liksom exempelvis ett char-pekare existerar enstaka ytterligare datatyp än ett int-pekare. (Den viktigaste skillnaden existerar för att pekartypen avgör hur informationen inom minnescellerna skall tolkas.

    Här får du lära dig hur du får i dig tillräckligt med A-vitamin genom kosten, vad A-vitamin är bra för, samt vad som händer om du får i dig för lite eller för mycket

    enstaka char-pekare vilket pekar vid enstaka integer skulle ge konstiga påverkan angående man önskar studera alternativt notera värden.)

    Nu kommer avdelningens huvudpunkt såsom en påstående: myArr inom exemplet ovan existerar även den enstaka int-pekare! oss reviderar bilden från datorminnet ovan. således på denna plats ser detta "egentligen" ut:

    Adress:

    00

    01

    02

    03

    04

    05

    06

    07

    08

    09

    10

    11

    12

    13

    14

    Celler:

    5

    00

    131

    12

    9999

    45

    45

    11

    02

    04

    0

    0

    100

    1

    47


    oss besitter fått sex minnesceller allokerade samt myArr existerar ett pekare såsom pekar vid den inledande minnescellen.

    önskar oss nedteckna ut inledande elementet, existerar dessa numeriskt värde rader identiska:

    cout << myArr[0];

    cout << *myArr;

    Vi förstår för tillfället varför man börjar räkna vid noll inom C++. "Nollte elementet" betyder för att man äger stegat sig fram noll steg. Man kunna nyttja klammernotationen vid samtliga pekare.

    Exempel:

    int myArr[6];

    int* myptr;

    myptr = myArr; // för tillfället pekar myptr vid inledande elementet.

    // Jämför exemplet ovan, raderna fullfölja identisk sak!

    myptr[4]=314;// detta femte elementet inom myArr, genom myptr

    Också andra aritmetiska operationer existerar tillåtna vid pekare: +, --, -, +=.

    Man är kapabel även nyttja jämförelseoperatorerna till för att jämföra numeriskt värde pekare.

    Sammanfattningsvis gäller alltså: *(myptr+i) existerar precist identisk sak likt myptr[i].

    Ska pekararitmetik användas?

    Att nyttja pekararitmetik på grund av vanliga arrayer (oavsett angående dem existerar statiskt alternativt dynamiskt allokerade - titta nästa avsnitt) uppfattas från dem flesta liksom krångligt samt onödigt.

    samt detta tillsammans all rätt! Jämför t.ex.

    int arr[6];

    for (int* ip = arr; ip < (arr+6); ip++)

    *ip = 0;

    med

    int arr[6];

    for (int inom = 0; inom < 6; i++)

    ip[i] = 0;

    som utför identisk sak. oss kunna möjligen frestas tro för att den inledande loopen existerar effektivare eftersom den existerar "på lägre nivå" dock enstaka god program som översätter kod genererar precist identisk kod på grund av dem numeriskt värde kodnuttarns.

    Av ovanstående framgår för att detta enkla svaret vid rubrikens fråga existerar nej! Anledningen mot för att oss tar upp detta inom kursen existerar två: dels på grund av för att ge medvetande på grund av vad pekare existerar, dels på grund av för att detta sätt för att tänka används inom standardbibliotekets klasser samt algoritmer (som beskrivs inom avsnittet Standardbiblioteket).

    Operatorn sizeof samt pekare

    En skillnad mellan den statiskt allokerade myArr samt pekaren myptr existerar dock för att sizeof-operatorn ger olika påverkan. sizof(myArr) ger minnesanvändningen på grund av läka arrayen, medan sizeof(myptr) bara ger minnesutrymmet på grund av pekaren.

    En skillnad mot mellan pekare samt arrayer

    Ytterligare enstaka skillnad mellan myArr samt myptr existerar för att man ej får ändra värdet vid myArr (myArr += 2 t.ex.

    existerar inte tillåtet), däremot är kapabel man nyttja den på grund av ytterligare pekararitmetik. Dessa numeriskt värde satser existerar således identiska:

    cout << *(myArr + 2) << endl;

    cout << myArr[2] << endl;

    Återigen: använd ej pekaritmetik: skriv myArr[2], ej *(myArr+2). Koden blir många läsligare.

    Pekare samt arrayer vilket funktionsparametrar

    Vi äger tidigare deklarerat ett funktion vilket skall ta arrayparametrar sålunda här:

    int sum( int a[], int size);

    Av dem ovanstående bör detta äga framgått för att nedanstående deklaration existerar helt ekvivalent:

    int sum( int* a, int size);

    Dynamisk allokering från arrayer

    Ett bekymmer tillsammans med arrayer existerar för att deras storlekar måste bestämmas nära kodningen.

    Man måste då ta mot "worst case"-utrymme, vilket existerar slösaktigt tillsammans minne. Genom för att nyttja new-operatorn kunna man allokera minne inom körningsögonblicket.

    Glöm inte att berätta för läkaren om du tar kosttillskott eller receptfria läkemedel

    new-operatorn utför numeriskt värde saker:

    1.    Den allokerar minne till därför flera objekt man anger liksom inargument. (eller en enda objekt angående man använder operatorn utan [ ]).

    2.      Den returnerar enstaka pekare mot detta inledande från dessa objekt.

    Exempel:

    char *c = new char; // Minne allokeras på grund av en enda tecken

    *c = 'a';// .. såsom sätts mot 'a'

    int size;

    cin >> size;

    int* myArr;

    myArr = new int[size]; // Minne allokeras till storlek st. int,

    // myArr pekar vid den inledande från dessa

    myArr[0]=3; // idag kunna oss nyttja myArr liksom enstaka vanlig array

    Det existerar många ovanligt samt oftast slöseri tillsammans med minne för att dynamiskt allokera utrymme på grund av enstaka chars, ints samt liknande (enstaka objekt existerar ett helt ytterligare bakgrund, tillsammans med detta återkommer oss mot senare beneath kursen!).

    Om man avbryter behandlingen plötsligt efter långtidsbehandling kan så kallade utsättningssymptom förekomma

    Att komma ihåg

    Precis liksom inom fallet tillsammans statiskt allokerade arrayer existerar detta viktigt för att komma minnas för att ej notera utanför arrayen! detta upptäcks ej nära kompilering (naturligtvis), samt leder mot segmentation fault alternativt dylikt nära körningen. Situationen inom vår datorminnesmodell existerar noggrann såsom inom förra illustrationen, dock oss besitter allokerat detaljerad sålunda flera element vilket oss vet från oss behöver.

    När man allokerar minne vid personlig grabb, existerar detta ens eget ansvar för att minnet lämnas tillbaka då detta ej längre behövs. ett minnesregel existerar för att detta på grund av varenda new inom programmet skall finnas enstaka delete. Operatorn delete lämnar igen minnet. angående man ej fullfölja detta, kommer mer samt mer minne för att reserveras utan för att detta används.

    Allokerat minne får ej användas från något annat än detta liksom allokerat detta, alltså går minnet tappat bort eller missat. Man får ett minnesläcka. inom exemplet ovan skulle oss behöva nedteckna

    // Avallokerar minnet oss reserverade ovan

    delete c;

    delete[] myArr;

    Klamrarna behövs bara då detta handlar ifall arrayer - dock då existerar detta viktigt för att man ej minns ej dem!

    Sammanfattning, arrayer

    ·         är enstaka indexerad sekvens från likadana element

    ·         första elementet äger ständigt index 0 samt dess sista arraystorlek-1

    ·         varje element förmå hanteras vilket en variabel från arrayens datatyp

    ·         vid parameteröverföring: adressen överförs, dvs detta ser ut såsom call bygd reference

    ·         en funktion är kapabel inte någonsin att fatta beslut eller bestämma något enstaka arrays längd

    ·         Eftersom pekare samt arrayer existerar identisk sak existerar funktionsdeklarationerna
    void myfunc( int a[] ); och
    void myfund (int *a);
    ekvivalenta.

    Statiska arrayer:

    ·         deklaration från ett endimensionell array: datatyp arraynamn[arraystorlek]

    ·         minnesutrymme allokeras nära kompileringen

    ·         måste ta hänsyn mot "worst case"

    ·         ineffektivt minnesutnyttjande

    Dynamiska arrayer

    ·         storleken bestäms nära exekveringen

    ·         en pekare deklareras, new samt delete används till för att allokera resp.

    avallokera minne

    ·         bättre utnyttjande från minnet

    ·         flexibelt

    ·         lite krångligare

    Exempel, dynamisk minnesallokering

    Antag för att man äger enstaka fil tillsammans temperaturer på grund av en antal dagar.

    ursprunglig inom filen finns antal mätvärden, sedan datum till inledande ljus tillsammans uppmätt temperatur. Därefter följer antal rader tillsammans temperaturer. Exempel:

    5

    20040101

    -10.2

    -6.7

    -5.6

    1.2

    -0.2

    En funktion såsom läser in uppgifter ifrån denna fil kunna titta ut sålunda här:

    double* getdata( string filnamn, int &antal,

    int &datum)

    {

    ifstream is( filnamn.c_str());

    is >> antal;

    is >> datum;

    double *d = new double[antal];

    for (int i=0; inom < antal; i++)

    is >> d[i];

    return d;

    }

    Flerdimensionella arrayer

    Om man önskar allokera ett dynamisk flerdimensionell array är kapabel man inom C++ inte notera något inom stil med:

    int *a = new int[3][3]

    Detta vore bekvämt, dock strukturen på grund av flerdimensionella dynamiska arrayer existerar likt följer: man skaffar sig tre (i detta fall) endimensionella arrayer:

    int *arr1 = new int[3];

    int *arr2 = new int[3];

    int *arr3 = new int[3];

    Vårt omhuldade minne (som oss för tillfället startar angående ifrån 00 i):

    Adress:

    00

    01

    02

    03

    04

    05

    06

    07

    08

    09

    10

    11

    1012

    1013

    1014

    Celler:

    123

    132

    131

    00

    0

    45

    45

    04

    19

    0

    0

    08

    100

    1

    47

    Våra tre pekare besitter hamnat inom adresserna 03, 07 samt 11.

    fanns samt ett från dessa pekare pekar vid sin lilla array. Hur bör oss idag skaffa oss enstaka tvådimensionell array. Jo, oss måste - innan oss allokerar område i enlighet med ovan - allokera ett dynamisk array från pekarvariabler samt sätta dem tre elementen inom denna för att peka vid fanns samt ett från dem tre int-arrayerna. D.v.s. oss skriver således här:

    int **arr = new int*[3];

    Observera variabeln arr liksom äger numeriskt värde asterisker, dvs *-tecken.

    Detta är kapabel titta märkligt ut dock blir möjligen klarare angående man skriver därför denna plats tillsammans typedef (vilket existerar helt likvärdig tillsammans med ovanstående):

    typedef int *intPointer;

    intPointer *arr = new intPointer[3];

    Nu ser oss klart för att oss äger allokerat lokal till enstaka array från pekare.

    Nästa steg existerar för att allokera lokal till själva data-arrayerna:

    int **arr = new int*[3];

    for ( int inom = 0; inom < 3; i++ )

    {

    arr[i] = new int[3];

    }

    // sätt diagonalelementen mot rad/kolumn,

    // resten = 0

    for ( int inom = 0; inom < 3; i++ )

    {

    for ( int j = 0; j < 3; j++ )

    {

    if ( i==j )

    arr[i][j] = i+1;

    else

    arr[i][j] = 0;

    }

    }

    Nu ser vårt minne ut därför här:

    Adress:

    00

    01

    02

    03

    04

    05

    06

    07

    08

    09

    10

    11

    12

    13

    14

    Celler:

    04

    07

    10

    00

    1

    0

    0

    0

    2

    0

    0

    0

    3

    1

    47


    d.v.s.

    variabeln arr äger hamnat inom minnescell 03 samt pekar vid elementet arr[0] (i minnescell 00) vilket egen existerar enstaka dynamiskt allokerad array samt pekar ut arrayen liksom börjar inom minnescell 04.

    Vi kunna nyttja arrayen t.ex. således här:

    arr[1][2] = 12;

    cout << arr[2][0];

    Avallokeringen måste ske inom omvänd ordning:

    for ( int inom = 0; inom < 3; i++ )

    delete[] arr[i];

    delete[] arr;

    Observera för att tillsammans ovanstående struktur finns detta ingenting vilket hindrar oss ifrån för att låta delarrayerna artikel olika långa.

    oss är kapabel t.ex. nedteckna därför här:

    int **arr = new int*[3];

    for ( int inom = 0; inom < 3; i++ )

    {

    arr[i] = new int[i+1];

    for ( int j = 0; j < i; j++ )

    arr[i][j] = i+1;

    }

    Minnet får för tillfället nästa utseende:

    Adress:

    00

    01

    02

    03

    04

    05

    06

    07

    08

    09

    10

    11

    12

    13

    14

    Celler:

    04

    05

    07

    00

    1

    2

    2

    3

    3

    3

    0

    0

    100

    1

    47


    och vår array får nästa struktur:

    1

    2 2

    3 3 3

    d.v.s.

    raderna existerar olika långa.

    Samma princip gäller till mångdimensionella arrayer: detta blir lika flera asterisker likt dimensioner.

    typedef igen

    Med hjälpa från typedef förmå man förenkla skrivsättet något nära dynamisk allokering från tvådimensionella arrayer. Exempel:

    typedef int IntArr[3]; // definierar ett typ "int[3]"

    IntArr *twodarr = new IntArr[3]; // twodarr fryst vatten now 3x3

    Eftersom oss äger bara ett new räcker även ett delete på grund av för att återlämna minnet:

    delete[] twodarr;

    Exempel, 2D-array

    Detta segment visar en modell vid dynamiskt allokerade arrayer samt demonstrerar för att man kunna äga pekare mot pekare.

    oss tänker oss för att oss skall bokföra flera serier från mätningar från något. då oss skriver programmet vet oss ej hur flera serier oss kommer för att lägga in, ej heller hur flera test varenda serie innehåller. oss måste alltså äga dynamisk allokering inom numeriskt värde dimensioner.

    v

    Deklation samt allokering blir:

    int numOfSeries;

    double** data;// mätserierna

    int* size;// mätseriernas längd

    cout << "Hur flera serier? ";

    cin >> numOfSeries;

    data = new double*[nuOfSeries];

    size = new int[nuOfSeries];

    for(int i=0; i<numOfSeries; i++)

    {

    cout<<"hur flera test innehåller serie "<<i<<": ";

    cin>>size[i];

    data[i] = new double[size[i]];

    double *ptr = data[i];

    for(int j=0; j<size[i]; j++)

    {

    cout<<"Ange värde "<<j<<" inom serie "<<i<<": ";

    cin>>ptr[j];

    }

    }

    och återlämnande från minne:

    for(int i=0; i<numOfSeries; i++)

    delete[] data[i];

    delete[] data;

    Pekare samt referenser

    Referenser existerar även enstaka sorts pekare.

    mot skillnad ifrån enstaka pekare måste ett referens ständigt referera något, man är kapabel ej äga 0-referenser alternativt felaktiga referenser. ett referens existerar en alias