C ++

Hur man använder C ++ pekare

Hur man använder C ++ pekare
Minnet på en dator är en lång serie celler. Storleken på varje cell kallas en byte. En byte är ett utrymme som upptas av en engelsk alfabetisk karaktär. Ett objekt i vanlig mening är en följd av byte i minnet. Varje cell har en adress, som är ett heltal, vanligtvis skrivet i hexadecimal form. Det finns tre sätt att komma åt ett objekt i minnet. Ett objekt kan nås med hjälp av en så kallad pekare. Den kan nås med hjälp av en så kallad referens. Det kan fortfarande nås med en identifierare. Fokus för denna artikel är användningen av pekare och referenser. I C ++ finns det spetsiga objektet och pekarobjektet. Det spetsiga föremålet har föremålet av intresse. Pekarobjektet har adressen till det spetsiga objektet.

Du måste ha grundläggande kunskaper i C ++, inklusive dess identifierare, funktioner och matriser; för att förstå den här artikeln.

Pekaren och det spetsiga objektet har var och en sin identifierare.

Adressen till operatören, &

Detta är en unary operatör. När den följs av en identifierare returnerar den adressen till objektet för identifieraren. Tänk på följande förklaring:

int ptdInt;

Nedan följer koden, följande uttryck, den adress som identifieras av ptdInt:

& ptdInt

Du behöver inte veta exakt adress (nummer) när du kodar.

Indirection Operator, *

Detta är en enhetlig operatör i samband med pekare. Det skrivs vanligtvis framför en identifierare. Om den används i en deklaration av identifieraren är identifieraren det pekarobjekt som endast innehåller adressen för det spetsiga objektet. Om den används framför pekarens objektidentifierare, för att returnera något, är den returnerade saken värdet på det spetsiga objektet.

Skapa en pekare

Ta en titt på följande kodsegment:

float ptdFloat;
float * ptrFloat;
ptrFoat = &ptdFloat;

Segmentet börjar med deklarationen av det spetsiga objektet, ptdFloat. ptdFloat är en identifierare som bara identifierar ett flytobjekt. Ett verkligt objekt (värde) kunde ha tilldelats det, men i det här fallet har inget tilldelats det. Nästa i segmentet är deklarationen av pekarens objekt. Indirection-operatören framför denna identifierare betyder att den måste hålla adressen till ett spetsigt objekt. Objekttypen, flyta i början av uttalandet, betyder att det spetsiga objektet är ett flottör. Pekarobjektet är alltid av samma typ som det spetsiga objektet. ptrFoat är en identifierare som bara identifierar ett pekarobjekt.

I det sista uttalandet av koden tilldelas pekobjektet adressen till det pekade objektet. Notera användningen av operatörens adress, &.

Det sista uttalandet (raden) ovan visar att du efter att deklarera pekareobjektet utan initialisering inte behöver indirection-operatören när du måste initialisera det. Det är faktiskt ett syntaxfel att använda indirection-operatören i den tredje (sista) raden.

Pekarobjektet kan deklareras och initialiseras av det spetsiga objektet i ett uttalande, enligt följande:

float ptdFloat;
flyta * ptrFoat = &ptdFloat;

Den första raden i föregående kodsegment och den här är desamma. Den andra och tredje raden i det föregående kodsegmentet har kombinerats till ett uttalande här.

Observera i ovanstående kod att indirection-operatören måste användas vid deklarering och initialisering av pekarobjektet. Det används dock inte om initialiseringen ska göras efteråt. Pekarobjektet initialiseras med adressen till det spetsiga objektet.

I följande kodsegment används indirection-operatören för att returnera innehållet i det spetsiga objektet.

int ptdInt = 5;
int * ptrInt = &ptdInt;
cout << *ptrInt << '\n';

Utgången är 5.

I det sista uttalandet här har indirection-operatören använts för att returnera det värde som pekas på, genom pekarens identifierare. Så, när den används i en deklaration, skulle identifieraren för indirection-operatören hålla det spetsiga objektets adress. När det används i ett returuttryck, i kombination med pekarens identifierare, returnerar indirection-operatören värdet på det spetsiga objektet.

Tilldela noll till en pekare

Pekaren ska alltid ha typen av det spetsiga objektet. När du förklarar pekarobjektet måste datatypen för det spetsiga objektet användas. Värdet för decimal noll kan dock tilldelas pekaren som i följande kodsegment:

int ptdInt = 5;
int * ptrInt;
ptrInt = 0;
eller i segmentet,
int ptdInt = 5;
int * ptrInt = 0;

I båda fallen kallas pekaren (identifieraren) nullpekaren; betyder, det pekar på ingenstans. Det vill säga, den har inte adressen till något spetsigt objekt. Här är 0 decimal noll och inte hexadecimal noll. Hexadecimal noll skulle peka på datorns minnes första adress.

Försök inte få det värde som en nollpekare pekar på. Om du försöker det kan programmet kompileras men kanske inte köras.

Array Name som en konstant pekare

Tänk på följande array:

int arr [] = 000, 100, 200, 300, 400;

Arrayens namn, arr är faktiskt den identifierare som har adressen till det första elementet i arrayen. Följande uttryck returnerar det första värdet i matrisen:

* arr

Med matrisen beter sig inkrementoperatören ++ annorlunda. Istället för att lägga till 1 ersätter den pekarens adress med adressen till nästa element i matrisen. Namnet på arrayen är dock en konstant pekare; vilket innebär att dess innehåll (adress) inte kan ändras eller ökas. Så, för att öka, måste startadressen för matrisen tilldelas en icke-konstant pekare enligt följande:

int * ptr = arr;

Nu kan ptr ökas för att peka på nästa element i matrisen. ptr har förklarats här som ett pekarobjekt. Utan * här skulle det inte vara en pekare; det skulle vara en identifierare att hålla ett int-objekt och inte att hålla en minnesadress.

Följande kodsegment pekar äntligen på det fjärde elementet:

++ptr;
++ptr;
++ptr;

Följande kod matar ut det fjärde värdet i matrisen:

int arr [] = 000, 100, 200, 300, 400;
int * ptr = arr;
++ptr;
++ptr;
++ptr;
cout << *ptr << '\n';

Utgången är 300.

Funktionsnamn som identifierare

Namnet på en funktion är funktionens identifierare. Tänk på följande funktionsdefinition:

int fn ()

cout << "seen" << '\n';
retur 4;

fn är funktionens identifierare. Uttrycket,

& fn

returnerar funktionens adress i minnet. fn är som det spetsiga föremålet. Följande deklaration förklarar en pekare till en funktion:

int (* func) ();

Identifieraren för det spetsiga objektet och identifieraren för pekaren är olika. func är en pekare till en funktion. fn är identifieraren för en funktion. Och så kan funk göras för att peka på fn enligt följande:

func = &fn;

Värdet (innehållet) i func är adressen till fn. De två identifierarna kunde ha länkats till ett initialiseringsuttalande enligt följande:

int (* func) () = &fn;

Notera skillnaderna och likheterna i hantering av funktionspekare och skalpekare. funk är en pekare till en funktion; det är det spetsiga föremålet; det förklaras annorlunda än en skalärpekare.

Funktionen kan anropas med,

fn ()
eller
funk ()

Det kan inte anropas med * func ().

När funktionen har parametrar har de andra parenteserna parametertyperna och behöver inte ha identifierarna för parametrarna. Följande program illustrerar detta:

#omfatta
använder namnrymd std;
float fn (float fl, int in)

retur fl;

int main ()

float (* func) (float, int) = &fn;
float val = func (2.5, 6);
cout << val << '\n';
returnera 0;

Utgången är 2.5.

C ++ referens

Att referera i C ++ är bara ett sätt att producera en synonym (ett annat namn) för en identifierare. Den använder & operator, men inte på samma sätt som & används för pekare. Tänk på följande kodsegment:

int mynt = 8;
int & yourInt = myInt;
cout << myInt << '\n';
cout << yourInt << '\n';

Utgången är:

8
8

Det första uttalandet initialiserar identifieraren, myInt; i.e. myInt deklareras och görs för att hålla värdet, 8. Det andra uttalandet gör en ny identifierare, dinInt en synonym till myInt. För att uppnå detta placeras & -operatören mellan datatypen och den nya identifieraren i deklarationen. Cout uttalanden visar att de två identifierarna är synonymer. För att returnera värdet i det här fallet behöver du inte föregå det med * . Använd bara identifieraren.

myInt och yourInt här, är inte två olika objekt. De är två olika identifierare som refererar till (identifierar) samma plats i minnet som har värdet 8. Om värdet på myInt ändras ändras också värdet på yourInt automatiskt. Om värdet på dinInt ändras ändras också värdet på myInt automatiskt.

Referenser är av samma typ.

Hänvisning till en funktion

Precis som du kan ha en hänvisning till en skalär kan du också ha en hänvisning till en funktion. Kodning av en referens till en funktion skiljer sig dock från kodning av en referens till en skalar. Följande program illustrerar detta:

#omfatta
använder namnrymd std;
float fn (float fl, int in)

retur fl;

int main ()

float (& func) (float, int) = fn;
float val = func (2.5, 6);
cout << val << '\n';
returnera 0;

Utgången är 2.5.

Notera det första uttalandet i huvudfunktionen, vilket gör funk till en synonym för fn. Båda refererar till samma funktion. Notera engångsanvändningen och placeringen av &. Så & är referensoperatören här och inte operatörens adress. För att ringa funktionen, använd bara något av namnen.

En referensidentifierare är inte densamma som en pekareidentifierare.

Funktion som returnerar en pekare

I följande program returnerar funktionen en pekare, som är adressen till det spetsiga objektet:

#omfatta
använder namnrymd std;
float * fn (float fl, int in)

flyta * fll = &fl;
retur fll;

int main ()

flyta * val = fn (2.5, 6);
cout << *val << '\n';
returnera 0;

Utgången är 2.5

Det första påståendet i funktionen, fn () är det bara för att skapa ett pekarobjekt. Observera engångsbruk och position för * i funktionssignaturen. Observera också hur pekaren (adress), mottogs i huvudfunktionen () av ​​ett annat pekarobjekt.

Funktion som returnerar en referens

I följande program returnerar funktionen en referens:

#omfatta
använder namnrymd std;
float & fn (float fl, int in)

flyta & frr = fl;
returnera frr;

int main ()

float & val = fn (2.5, 6);
cout << val << '\n';
returnera 0;

Utgången är 2.5.

Det första uttalandet i funktionen, fn () är det bara för att skapa en referens. Observera engångsbruk och position för & i funktionssignaturen. Observera också hur referensen togs emot i huvudfunktionen () av ​​en annan referens.

Skicka en pekare till en funktion

I följande program skickas en pekare, som faktiskt är adressen till ett flytande objekt, som ett argument till funktionen:

#omfatta
använder namnrymd std;
float fn (float * fl, int in)

returnera * fl;

int main ()

flottör v = 2.5;
float val = fn (& v, 6);
cout << val << '\n';
returnera 0;

Utgången är 2.5

Notera användningen och placeringen av * för flottörparametern i funktionssignaturen. Så snart utvärderingen av fn () -funktionen startar görs följande uttalande:

flyta * fl = & v;

Både fl och & pekar mot samma spetsiga föremål som rymmer 2.5. * fl vid returuttalandet är inte en deklaration; det betyder, värdet på det spetsiga objektet som pekarobjektet pekar på.

Skicka en referens till en funktion

I följande program skickas en referens som ett argument till funktionen:

#omfatta
använder namnrymd std;
float fn (float & fl, int in)

retur fl;

int main ()

flottör v = 2.5;
flottörval = fn (v, 6);
cout << val << '\n';
returnera 0;

Utgången är 2.5

Notera användningen och placeringen av & för flottörparametern i funktionssignaturen. Så snart utvärderingen av fn () -funktionen startar görs följande uttalande:

flyta & fl = v;

Förmedla en matris till en funktion

Följande program visar hur man skickar en matris till en funktion:

#omfatta
använder namnrymd std;
int fn (int arra [])

returnera arra [2];

int main ()

int arr [] = 000, 100, 200, 300, 400;
int val = fn (arr);
cout << val << '\n';
returnera 0;

Utgången är 200.

I det här programmet är det matrisen som skickas. Observera att parametern för funktionssignaturen har en tom arraydeklaration. Argumentet i funktionsanropet är bara namnet på en skapad matris.

Kan en C ++ - funktion returnera en matris?

En funktion i C ++ kan returnera värdet för en array, men kan inte returnera arrayen. Sammanställningen av följande program resulterar i ett felmeddelande:

#omfatta
använder namnrymd std;
int fn (int arra [])

returnera arra;

int main ()

int arr [] = 000, 100, 200, 300, 400;
int val = fn (arr);
returnera 0;

Pekare på en pekare

En pekare kan peka på en annan pekare. Det vill säga ett pekarobjekt kan ha adressen till ett annat pekarobjekt. De måste fortfarande alla vara av samma typ. Följande kodsegment illustrerar detta:

int ptdInt = 5;
int * ptrInt = &ptdInt;
int ** ptrptrInt = &ptrInt;
cout << **ptrptrInt << '\n';

Utgången är 5.

I deklarationen av pekare till pekare används dubbel *. För att returnera värdet av det slutliga spetsiga objektet används fortfarande dubbelt *.

Array of Pointers

Följande program visar hur man kodar en rad pekare:

#omfatta
använder namnrymd std;
int main ()

int num0 = 000, num1 = 100, num2 = 200, num3 = 300, num4 = 400;
int * no0 = & num0, * no1 = & num1, * no2 = & num2, * no3 = & num3, * no4 =&num4;
int * arr [] = no0, no1, no2, no3, no4;
cout << *arr[4] << '\n';
returnera 0;

Utgången är:

400

Observera användningen och placeringen av * i deklarationen för matrisen. Observera användningen av * när du returnerar ett värde i matrisen. Med pekare av pekare är två * inblandade. När det gäller en rad pekare har en * redan tagits om, eftersom matrisidentifieraren är en pekare.

Array of Strängar med variabel längd

En sträng bokstavlig är en konstant som returnerar en pekare. En rad strängar med variabel längd är en rad pekare. Varje värde i matrisen är en pekare. Pekare är adresser till minnesplatser och har samma storlek. Strängarna av olika längd finns någon annanstans i minnet, inte i matrisen. Följande program illustrerar användningen:

#omfatta
använder namnrymd std;
int main ()

const char * arr [] = "kvinna", "pojke", "flicka", "vuxen";
cout << arr[2] << '\n';
returnera 0;

Produktionen är "flicka".

Arbetsdeklarationen börjar med det reserverade ordet "const" för konstant; följt av “char” för karaktären, sedan asterisken, * för att indikera att varje element är en pekare. För att returnera en sträng från matrisen används * inte på grund av den implicita karaktären hos pekaren för varje sträng. Om * används kommer det första elementet i strängen att returneras.

Pekare till en funktion som returnerar en pekare

Följande program illustrerar hur en pekare till en funktion som returnerar en pekare kodas:

#omfatta
använder namnrymd std;
int * fn ()

int num = 4;
int * inter = #
retur inter;

int main ()

int * (* func) () = &fn;
int val = * func ();
cout << val << '\n';
returnera 0;

Utgången är 4.

Deklarationen av en pekare till en funktion som returnerar en pekare liknar deklarationen av en pekare till en vanlig funktion men föregås av en asterisk. Det första uttalandet i huvudfunktionen () illustrerar detta. För att ringa upp funktionen med hjälp av pekaren, föregå den med *.

Slutsats

För att skapa en pekare till en skalär, gör något liknande,

flyta spetsig;
flyta * pekare = &pointed;

* har två betydelser: i en deklaration indikerar den en pekare; att returnera något är det för värdet av det spetsiga föremålet.

Arraynamnet är en konstant pekare till det första elementet i arrayen.

För att skapa en pekare till en funktion kan du göra,

int (* func) () = &fn;

där fn () är en funktion definierad någon annanstans och func är pekaren.

& har två betydelser: i en deklaration anger den en referens (synonym) till samma objekt som en annan identifierare; när du returnerar något betyder det adressen till.

För att skapa en referens till en funktion kan du göra,

float (& refFunc) (float, int) = fn;

där fn () är en funktion definierad någon annanstans och refFunc är referensen.

När en funktion returnerar en pekare måste det returnerade värdet tas emot av en pekare. När en funktion returnerar en referens måste det returnerade värdet tas emot av en referens.

När du skickar en pekare till en funktion är parametern en deklaration, medan argumentet är adressen till ett spetsigt objekt. När du skickar en referens till en funktion är parametern en deklaration, medan argumentet är referensen.

Vid överföring av en matris till en funktion är parametern en deklaration medan argumentet är matrisnamnet utan []. C ++ - funktionen returnerar inte en matris.

En pekare-till-pekare behöver två * istället för en, där så är lämpligt.

Chrys

Hur man visar OSD-överlägg i helskärms Linux-appar och -spel
Att spela helskärmsspel eller använda appar i distraktionsfritt helskärmsläge kan avskärma dig från relevant systeminformation som syns i en panel ell...
Topp 5 spelinspelningskort
Vi har alla sett och älskat streaming av spel på YouTube. PewDiePie, Jakesepticye och Markiplier är bara några av de bästa spelarna som har tjänat mil...
Hur man utvecklar ett spel på Linux
För ett decennium sedan skulle inte många Linux-användare förutsäga att deras favoritoperativsystem en dag skulle vara en populär spelplattform för ko...