C ++

Kuidas kasutada C ++ osutit

Kuidas kasutada C ++ osutit
Arvuti mälu on pikk rakkude rida. Iga lahtri suurust nimetatakse baidiks. Bait on ruum, mille hõivab tähestiku ingliskeelne tähemärk. Objekt tavamõistes on järjestikune baitide kogum mälus. Igal lahtril on aadress, mis on täisarv, mis on tavaliselt kirjutatud kuueteistkümnendsüsteemis. Mälus olevale objektile pääsemiseks on kolm võimalust. Objektile pääseb ligi, kasutades nn kursorit. Sellele pääseb juurde, kasutades nn viitena. Sellele pääseb endiselt juurde identifikaatori abil. Selle artikli keskmes on viidete ja viidete kasutamine. C ++ keeles on terav objekt ja osuti objekt. Terava esemega on huviobjekt. Kursoriobjektil on aadress teravale objektile.

Teil peavad olema põhiteadmised C ++ keeles, sealhulgas selle identifikaatorid, funktsioonid ja massiivid; sellest artiklist aru saada.

Kursoriobjektil ja teravdatud objektil on mõlemal oma identifikaator.

Operaatori aadress ja

See on unaarne operaator. Kui sellele järgneb identifikaator, tagastab see identifikaatori objekti aadressi. Mõelge järgmisele deklaratsioonile:

int ptdInt;

Allpool on kood, järgmine avaldis tagastab aadressi, mille identifitseeris ptdInt:

& ptdInt

Kodeerimisel ei pea te teadma täpset aadressi (numbrit).

Indirection operaator, *

See on osutite kontekstis unaarne operaator. Tavaliselt trükitakse see identifikaatori ette. Kui seda kasutatakse identifikaatori deklaratsioonis, on identifikaator kursoriobjekt, millel on ainult terava objekti aadress. Kui seda kasutatakse kursoriobjekti identifikaatori ees, tagastatakse midagi, siis on tagastatud asi terava objekti väärtus.

Kursori loomine

Heitke pilk järgmisele koodisegmendile:

ujuk ptdFloat;
ujuk * ptrFloat;
ptrFoat = &ptdFloat;

Segment algab terava objekti deklareerimisega ptdFloat. ptdFloat on identifikaator, mis lihtsalt tuvastab ujukobjekti. Sellele oleks võinud omistada tegeliku objekti (väärtuse), kuid sel juhul pole talle midagi määratud. Segmendi järgmisena on kursoriobjekti deklaratsioon. Selle identifikaatori ees olev suunaoperaator tähendab, et tal peab olema terava eseme aadress. Objekti tüüp, ujuk lause alguses, tähendab, et terav objekt on ujuk. Kursoriobjekt on alati sama tüüpi kui teravobjekt. ptrFoat on identifikaator, mis lihtsalt tuvastab kursoriobjekti.

Koodi viimases lauses määratakse terava objekti aadress osutiobjektile. Pange tähele operaatori address-operaatori ja.

Viimane ülaltoodud lause (rida) näitab, et pärast kursoriobjekti deklareerimist ilma initsialiseerimiseta pole teil vaja initsialiseerimisoperatsiooni. Tegelikult on kolmanda (viimase) rea indirection-operaatori kasutamine süntaksiviga.

Osutiobjekti saab deklareerida ja initsialiseerida terava objektiga ühes avalduses järgmiselt:

ujuk ptdFloat;
ujuk * ptrFoat = &ptdFloat;

Eelmise koodisegmendi esimene rida ja see on samad. Eelmise koodisegmendi teine ​​ja kolmas rida on siin ühendatud üheks avalduseks.

Pange ülaltoodud koodis tähele, et osutiobjekti deklareerimisel ja initsialiseerimisel tuleb kasutada suunamisoperaatorit. Kuid seda ei kasutata, kui lähtestamine tuleb teha hiljem. Kursoriobjekt lähtestatakse terava objekti aadressiga.

Järgmises koodisegmendis kasutatakse suunamata operaatorit terava objekti sisu tagastamiseks.

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

Väljund on 5.

Siinses viimases avalduses on indirection-operaatorit kasutatud osutatava väärtuse tagastamiseks kursori identifikaatori abil. Seega, kui seda kasutatakse deklaratsioonis, hoiab indirection-operaatori identifikaator terava objekti aadressi. Tagasilauses kasutatuna koos kursori identifikaatoriga tagastab indirection operaator terava objekti väärtuse.

Null määramine osutile

Kursoriobjektil peaks alati olema terava objekti tüüp. Kursoriobjekti deklareerimisel tuleb kasutada terava objekti andmetüüpi. Kümnendkoha nulli väärtuse saab aga osutada kursorile nagu järgmises koodisegmendis:

int ptdInt = 5;
int * ptrInt;
ptrInt = 0;
või segmendis,
int ptdInt = 5;
int * ptrInt = 0;

Mõlemal juhul nimetatakse kursorit (identifikaatorit) nullkursoriks; tähenduses osutab see kuhugi. See tähendab, et sellel pole ühegi terava objekti aadressi. Siin on 0 kümnendkohani, mitte kuueteistkümnendkohani. Kuueteistkümnendkohaga null osutaks arvutimälu esimesele aadressile.

Ärge proovige saada väärtust, millele nullkursor osutab. Kui proovite seda, võib programm kompileerida, kuid ei pruugi käivitada.

Massiivi nimi pideva osutina

Mõelge järgmisele massiivile:

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

Massiivi nimi arr on tegelikult identifikaator, millel on massiivi esimese elemendi aadress. Järgmine avaldis tagastab massiivi esimese väärtuse:

* arr

Massiivi korral käitub juurdekasvuoperaator ++ erinevalt. 1 asemel lisab see osuti aadressi massiivi järgmise elemendi aadressiga. Massiivi nimi on aga pidev osuti; mis tähendab, et selle sisu (aadressi) ei saa muuta ega suurendada. Niisiis tuleb massiivi algusaadress määrata mittekonstantse osuti jaoks järgmiselt:

int * ptr = arr;

Nüüd saab ptr-i suurendada massiivi järgmise elemendi osutamiseks. ptr on siin deklareeritud osutiobjektina. Ilma siin * poleks see osuti; identifikaator oleks int-objekti hoidmine ja mitte mäluaadressi hoidmine.

Järgmine koodisegment osutab lõpuks neljandale elemendile:

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

Järgmine kood väljastab massiivi neljanda väärtuse:

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

Väljund on 300.

Funktsiooni nimi identifikaatorina

Funktsiooni nimi on funktsiooni identifikaator. Mõelge järgmisele funktsiooni määratlusele:

int fn ()

cout << "seen" << '\n';
tagasipöördumine 4;

fn on funktsiooni identifikaator. Väljend,

& fn

tagastab mälus oleva funktsiooni aadressi. fn on nagu terav objekt. Järgmine deklaratsioon deklareerib funktsiooni kursori:

int (* func) ();

Terava objekti identifikaator ja kursori objekti identifikaator on erinevad. func on funktsiooni kursor. fn on funktsiooni identifikaator. Ja nii saab funktsiooni fn-le osutada järgmiselt:

func = &fn;

Funktsiooni func väärtus (sisu) on fn aadress. Need kaks identifikaatorit oleks võinud olla seotud initsialiseerimislausega järgmiselt:

int (* func) () = &fn;

Pange tähele funktsiooni osutajate ja skalaarkursorite käsitlemise erinevusi ja sarnasusi. func on funktsiooni kursor; see on terav ese; see deklareeritakse skalaarkursorist erinevalt.

Funktsiooni saab kutsuda,

fn ()
või
func ()

Seda ei saa kutsuda funktsiooniga * func ().

Kui funktsioonil on parameetrid, on teistes sulgudes parameetrite tüübid ja neil ei pea olema parameetrite identifikaatoreid. Järgmine programm illustreerib seda:

# kaasata
nimeruumi kasutamine std;
float fn (float fl, int in)

tagasi fl;

int main ()

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

Väljund on 2.5.

C ++ viide

Viitamine C ++ keeles on lihtsalt viis identifikaatori sünonüümi (teise nime) loomiseks. See kasutab & operaatorit, kuid mitte samamoodi nagu & osutite jaoks. Mõelge järgmisele koodisegmendile:

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

Väljund on:

8
8

Esimene lause initsialiseerib identifikaatori myInt; i.e. myInt deklareeritakse ja pannakse seda väärtust hoidma, 8. Teine lause muudab uue identifikaatori, yourInt on myInt sünonüüm. Selle saavutamiseks paigutatakse & operaator deklaratsioonis andmetüübi ja uue identifikaatori vahele. Couti avaldused näitavad, et kaks identifikaatorit on sünonüümid. Väärtuse tagastamiseks ei pea te sellele eelnema * . Kasutage lihtsalt identifikaatorit.

myInt ja sinu siin pole kaks erinevat objekti. Need on kaks erinevat identifikaatorit, mis viitavad (identifitseerivad) samale asukohale mälus, mille väärtus on 8. Kui myInti väärtust muudetakse, muutub ka teieInt väärtus automaatselt. Kui teieInt väärtust muudetakse, muutub ka myInt väärtus automaatselt.

Viited on sama tüüpi.

Viide funktsioonile

Nii nagu teil võib olla viide skalaarile, võib teil olla ka viide funktsioonile. Funktsioonile viite kodeerimine erineb aga skalaari viite kodeerimisest. Järgmine programm illustreerib seda:

# kaasata
nimeruumi kasutamine std;
float fn (float fl, int in)

tagasi fl;

int main ()

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

Väljund on 2.5.

Pange tähele peafunktsiooni esimest lauset, mis muudab funktsiooni fn sünonüümiks. Mõlemad viitavad samale funktsioonile. Pange tähele ühekordset kasutamist ja. Nii et siin on viideoperaator ja mitte operaatori aadress. Funktsiooni kutsumiseks kasutage lihtsalt ühte või teist nime.

Viitetunnus ei ole sama kui osuti tunnus.

Kursori tagastamise funktsioon

Järgmises programmis tagastab funktsioon osuti, mis on terava objekti aadress:

# kaasata
nimeruumi kasutamine std;
ujuk * fn (ujuk fl, int sisse)

ujuk * fll = &fl;
tagasipöördumine fll;

int main ()

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

Väljund on 2.5

Funktsiooni esimene lause fn () on lihtsalt kursoriobjekti loomiseks. Pange tähele funktsiooni allkirjas ühekordset kasutamist ja * asukohta. Pange tähele ka seda, kuidas osuti (aadress) võeti funktsioonis main () vastu mõne muu kursoriobjekti poolt.

Funktsioon viite tagastamiseks

Järgmises programmis tagastab funktsioon viite:

# kaasata
nimeruumi kasutamine std;
float & fn (float fl, int in)

ujuk & frr = fl;
tagasipöördumine frr;

int main ()

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

Väljund on 2.5.

Funktsiooni esimene lause fn () on lihtsalt viite loomiseks. Pange tähele funktsiooni allkirja ühekordset kasutamist ja positsiooni. Pange tähele ka seda, kuidas viide põhifunktsioonis () teise viitega vastu võeti.

Kursori edastamine funktsioonile

Järgmises programmis saadetakse funktsioonile argumendina kursor, mis on tegelikult ujuka terava objekti aadress:

# kaasata
nimeruumi kasutamine std;
ujuk fn (ujuk * fl, int sisse)

tagasitulek * fl;

int main ()

ujuk v = 2.5;
ujuk val = fn (& v, 6);
cout << val << '\n';
tagastama 0;

Väljund on 2.5

Funktsiooni allkirjas märkige ujuki parameetri kasutamine ja asukoht *. Niipea kui funktsiooni fn () hindamine algab, tehakse järgmine lause:

ujuk * fl = & v;

Nii fl kui ka v osutavad samale teravale objektile, mis hoiab 2.5. * tagastamisavalduses olev fl pole deklaratsioon; see tähendab terava eseme väärtust, millele osutab kursori objekt.

Funktsioonile viite edastamine

Järgmises programmis saadetakse funktsiooni argumendina viide:

# kaasata
nimeruumi kasutamine std;
float fn (float & fl, int in)

tagasi fl;

int main ()

ujuk v = 2.5;
ujuk val = fn (v, 6);
cout << val << '\n';
tagastama 0;

Väljund on 2.5

Pange funktsiooni allkirjas tähele ujuki parameetri & asukoht ja asukoht. Niipea kui funktsiooni fn () hindamine algab, tehakse järgmine lause:

ujuk & fl = v;

Massiivi edastamine funktsioonile

Järgmine programm näitab, kuidas massiivi funktsioonile edastada:

# kaasata
nimeruumi kasutamine std;
int fn (int arra [])

tagasitulek [2];

int main ()

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

Väljund on 200.

Selles programmis edastatakse massiiv. Pange tähele, et funktsiooni signatuuri parameetril on tühi massiivideklaratsioon. Funktsioonikõne argument on ainult loodud massiivi nimi.

Kas funktsioon C ++ saab massiivi tagastada?

Funktsioon C ++ võib tagastada massiivi väärtuse, kuid ei saa massiivi tagastada. Järgmise programmi kompileerimine annab tõrketeate:

# kaasata
nimeruumi kasutamine std;
int fn (int arra [])

tagastama arra;

int main ()

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

Kursori osuti

Kursor võib osutada teisele osutile. See tähendab, et osutiobjektil võib olla mõne muu kursoriobjekti aadress. Need peavad ikka kõik olema sama tüüpi. Järgmine koodilõik illustreerib seda:

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

Väljund on 5.

Osutaja-osuti deklaratsioonis kasutatakse topelt *. Viimase terava objekti väärtuse tagastamiseks kasutatakse endiselt topelt *.

Näidikute massiiv

Järgmine programm näitab, kuidas koodide massiivi kodeerida:

# kaasata
nimeruumi kasutamine 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 [] = ei0, no1, no2, no3, no4;
cout << *arr[4] << '\n';
tagastama 0;

Väljund on:

400

Massiivi deklaratsioonis märkige * kasutamine ja asukoht. Massiivi väärtuse tagastamisel märkige * kasutamine. Näpunäidikutega on kaasatud kaks *. Osutite massiivi korral on üks * juba hoolitsetud, kuna massiivi identifikaator on osuti.

Muutuva pikkusega stringide massiiv

Stringi literaal on konstant, mis tagastab kursori. Muutuva pikkusega stringide massiiv on osutite massiiv. Iga massiivi väärtus on osuti. Kursorid on aadressid mälukohti ja on sama suurusega. Erineva pikkusega stringid on mujal mälus, mitte massiivis. Järgmine programm illustreerib kasutamist:

# kaasata
nimeruumi kasutamine std;
int main ()

const char * arr [] = "naine", "poiss", "tüdruk", "täiskasvanu";
cout << arr[2] << '\n';
tagastama 0;

Väljundiks on “tüdruk”.

Massiivi deklaratsioon algab konstantiks reserveeritud sõnaga “const”; järgneb tähemärgi jaoks "char", seejärel tärn *, mis näitab, et iga element on osuti. Massiivilt stringi tagastamiseks ei kasutata *, kuna iga stringi osuti on vaikimisi iseloomulik. Kui kasutatakse *, tagastatakse stringi esimene element.

Kursor funktsiooni kursori tagastamiseks

Järgmine programm illustreerib, kuidas kursori tagastava funktsiooni kursor kodeeritakse:

# kaasata
nimeruumi kasutamine std;
int * fn ()

int arv = 4;
int * inter = #
tagasipöördumine;

int main ()

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

Väljund on 4.

Kursori tagastamine funktsioonile osutava kursori deklaratsioon on sarnane tavalise funktsiooni kursori deklaratsiooniga, kuid sellele eelneb tärn. Funktsiooni main () esimene väide illustreerib seda. Funktsiooni helistamiseks kursori abil eelistage sellele *.

Järeldus

Skalaari kursori loomiseks tehke midagi sellist,

ujuk terav;
ujuk * osuti = &pointed;

* on kahes tähenduses: deklaratsioonis tähistab see osutit; millegi tagastamiseks on see terava eseme väärtus.

Massiivi nimi on massiivi esimese elemendi pidev osuti.

Funktsioonile osuti loomiseks saate seda teha,

int (* func) () = &fn;

kus fn () on mujal määratletud funktsioon ja kursor funktsiooni func.

& on kaks tähendust: deklaratsioonis tähistab see viidet (sünonüümi) samale objektile teise identifikaatorina; millegi tagastamisel tähendab see aadressi.

Funktsioonile viite loomiseks saate seda teha,

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

kus fn () on mujal määratletud funktsioon ja refFunc on viide.

Kui funktsioon tagastab kursori, peab kursor tagastatava väärtuse vastu võtma. Kui funktsioon tagastab viite, peab tagastatud väärtuse saama viide.

Kursori edastamisel funktsioonile on parameetriks deklaratsioon, argumendiks aga terava objekti aadress. Funktsioonile viite edastamisel on parameeter deklaratsioon, samal ajal kui argument on viide.

Massiivi edastamisel funktsioonile on parameeter deklaratsioon, argumendiks aga massiivi nimi ilma []. Funktsioon C ++ ei tagasta massiivi.

Kursor-osuti vajab vajadusel ühe asemel kahte *.

Chrys

Kuidas muuta hiire vasakut ja paremat nuppu Windows 10 PC-s
On üsna tavaline, et kõik arvutihiirte seadmed on ergonoomiliselt mõeldud parempoolsete kasutajate jaoks. Kuid on olemas hiire seadmeid, mis on spetsi...
Jäljendage hiireklikke, hõljutades hiirega klõpsutut hiirt Windows 10-s
Hiire või klaviatuuri kasutamine liigses kasutamises vales asendis võib põhjustada palju terviseprobleeme, sealhulgas tüve, karpaalkanali sündroom ja ...
Nende tasuta tööriistade abil lisage Windows 10-le hiire liigutused
Viimastel aastatel on arvutid ja operatsioonisüsteemid palju arenenud. Oli aeg, mil kasutajad pidid failihaldurites navigeerimiseks kasutama käske. Na...