C ++

Avaldise kategooria taksonoomia C ++ keeles

Avaldise kategooria taksonoomia C ++ keeles

Arvutus on mis tahes tüüpi arvutus, mis järgib täpselt määratletud algoritmi. Avaldis on operaatorite ja operandide jada, mis määrab arvutuse. Teisisõnu, avaldis on identifikaator või literaal või mõlema järjestus, mis on ühendatud operaatoritega.Programmeerimisel võib avaldis põhjustada väärtuse ja / või põhjustada mõne juhtumise. Kui selle tulemuseks on väärtus, on avaldis glvalue, rvalue, lvalue, xvalue või prvalue. Kõik need kategooriad on väljendite kogum. Igal hulgal on määratlus ja konkreetsed olukorrad, kus selle tähendus valitseb, eristades seda teisest komplektist. Iga komplekti nimetatakse väärtusekategooriaks.

Märge: Väärtus või literaal on endiselt väljend, nii et need terminid klassifitseerivad väljendeid ja mitte tegelikult väärtusi.

glvalue ja rvalue on kaks alamhulka suure hulga avaldisest. glvalue eksisteerib veel kahes alamhulgas: lvalue ja xvalue. avaldise teine ​​alamhulk rvalue eksisteerib veel kahes alamhulgas: xvalue ja prvalue. Seega on xvalue nii glvalue kui rvalue alamhulk: see tähendab, et xvalue on nii glvalue kui rvalue lõikepunkt. Järgmine C ++ spetsifikatsioonist võetud taksonoomia diagramm illustreerib kõigi komplektide suhet:

prvalue, xvalue ja lvalue on peamised kategooria väärtused. glvalue on väärtuste ja xvalues ​​liit, samal ajal kui rvalues ​​on xvalues ​​ja prvalues ​​liit.

Selle artikli mõistmiseks vajate algteadmisi C ++ keeles; vajate ka teadmisi ulatusest C-s++.

Artikli sisu

Põhitõed

Avaldiste kategooria taksonoomia tõeliseks mõistmiseks peate kõigepealt meelde tuletama või teadma järgmisi põhifunktsioone: asukoht ja objekt, salvestusruum ja ressurss, initsialiseerimine, identifikaator ja viide, lvalue ja rvalue viited, kursor, tasuta pood ja a ressurss.

Asukoht ja objekt

Mõelge järgmisele deklaratsioonile:

int ident;

See on deklaratsioon, mis tuvastab asukoha mälus. Asukoht on konkreetne järjestikuste baitide kogum mälus. Asukoht võib koosneda ühest baidist, kahest baidist, neljast, 64 baidist jne. 32-bitise masina täisarvu asukoht on neli baiti. Samuti saab asukoha tuvastada identifikaatori abil.

Ülaltoodud deklaratsioonis pole asukohal mingit sisu. See tähendab, et sellel pole mingit väärtust, kuna väärtus on väärtus. Niisiis identifikaator tuvastab asukoha (väike pidev ruum). Kui asukohale antakse konkreetne sisu, identifitseerib identifikaator nii asukoha kui ka sisu; see tähendab, et identifikaator tuvastab seejärel nii asukoha kui ka väärtuse.

Mõelge järgmistele väidetele:

int ident1 = 5;
int ident2 = 100;

Kõik need väited on deklaratsioon ja määratlus. Esimesel identifikaatoril on väärtus (sisu) 5 ja teisel identifikaatoril väärtus 100. 32-bitises masinas on igaüks neist kohtadest neli baiti pikk. Esimene identifikaator tuvastab nii asukoha kui ka väärtuse. Teine identifikaator tuvastab ka mõlemad.

Objekt on nimeline mälupiirkond. Niisiis on objekt kas väärtuseta asukoht või väärtusega asukoht.

Objektide salvestamine ja ressurss

Objekti asukohta nimetatakse ka objekti salvestamiseks või ressursiks.

Initsialiseerimine

Mõelge järgmisele koodisegmendile:

int ident;
ident = 8;

Esimene rida deklareerib identifikaatori. See deklaratsioon annab täisobjekti asukoha (salvestusruumi või ressursi), identifitseerides selle nime, identiga. Järgmine rida paneb väärtuse 8 (bittides) identi identifitseeritud asukohta. Selle väärtuse panemine on initsialiseerimine.

Järgmine lause määratleb vektori, mille sisu on 1, 2, 3, 4, 5 ja mille tähistab vtr:

std: vektor vtr 1, 2, 3, 4, 5;

Siin tehakse initsialiseerimine 1, 2, 3, 4, 5 määratluse (deklaratsiooni) samas avaldises. Määramise operaatorit ei kasutata. Järgmine lause määratleb massiivi sisuga 1, 2, 3, 4, 5:

int arr [] = 1, 2, 3, 4, 5;

Seekord on lähtestamiseks kasutatud määranguoperaatorit.

Identifikaator ja viide

Mõelge järgmisele koodisegmendile:

int ident = 4;
int & ref1 = ident;
int & ref2 = ident;
cout<< ident <<"<< ref1 <<"<< ref2 << '\n';

Väljund on:

4 4 4

ident on identifikaator, samas kui ref1 ja ref2 on viited; nad viitavad samale asukohale. Viide on identifikaatori sünonüüm. Tavapäraselt on ref1 ja ref2 ühe objekti erinevad nimed, samas kui ident on sama objekti identifikaator. Kuid identi võib ikkagi nimetada objekti nimeks, mis tähendab sama asukoha nime ident, ref1 ja ref2.

Peamine erinevus identifikaatori ja viite vahel on see, et funktsiooni argumendina edastamise korral tehakse identifikaatori kaudu funktsiooni identifikaatorile koopia, samas kui viitena edastatakse sama asukoht funktsioon. Niisiis lõpeb identifikaatori kaudu möödumine kahe asukohaga, samas kui viitest möödumine lõpeb sama asukohaga.

lvalue Reference ja rvalue Reference

Normaalne viis viite loomiseks on järgmine:

int ident;
ident = 4;
int & ref = ident;

Kõigepealt asub ja tuvastatakse hoidla (ressurss) (nimega nagu ident) ja seejärel tehakse viide (nimega nagu viide). Funktsioonile argumendina edastades tehakse funktsioonis identifikaatori koopia, samas kui viite puhul kasutatakse (viidatakse) funktsioonis algset asukohta.

Tänapäeval on võimalik lihtsalt viidet omada seda tuvastamata. See tähendab, et kõigepealt on võimalik viide luua ilma asukoha identifikaatorita. See kasutab &&, nagu on näidatud järgmises avalduses:

int && ref = 4;

Siin puudub eelnev identifitseerimine. Objekti väärtusele juurde pääsemiseks kasutage lihtsalt ref-i, nagu kasutaksite ülaltoodud identiteeti.

&& deklaratsiooniga pole võimalust funktsiooni argumenti identifikaatori kaudu edastada. Ainus valik on anda viide. Sel juhul kasutatakse funktsiooni sees ainult ühte asukohta, mitte teist kopeeritud asukohta nagu identifikaatoriga.

& -Ga viidatud deklaratsiooni nimetatakse väärtuseks lvalue. Viidadeklaratsiooni koos && -ga nimetatakse rvalue-viiteks, mis on ka prvalue-viide (vt allpool).

Pointer

Mõelge järgmisele koodile:

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

Väljund on 5.

Siin on ptdInt identifikaator nagu ülaltoodud identiteet. Siin on ühe asemel kaks objekti (asukohta): terav objekt, ptdInt poolt identifitseeritud ptdInt ja ptrInt poolt tuvastatud osuti ptrInt. & ptdInt tagastab terava objekti aadressi ja paneb selle kursori ptrInt objekti väärtuseks. Terava objekti väärtuse tagastamiseks (saamiseks) kasutage kursoriobjekti identifikaatorit, nagu jaotises “* ptrInt”.

Märge: ptdInt on identifikaator, mitte viide, samas kui juba varem mainitud nimi ref on viide.

Ülaltoodud koodi teist ja kolmandat rida saab vähendada ühele reale, mis viib järgmise koodini:

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

Märge: Kui osuti suurendatakse, osutab see järgmisele asukohale, mis ei ole väärtuse 1 liitmine. Kui kursorit vähendatakse, osutab see eelmisele asukohale, mis ei ole väärtuse 1 lahutamine.

Tasuta pood

Operatsioonisüsteem eraldab iga töötava programmi jaoks mälu. Mälu, mida pole ühegi programmi jaoks eraldatud, nimetatakse tasuta poodiks. Avaldus, mis tagastab tasuta poest täisarvu asukoha, on:

uus int

See tagastab tuvastamata täisarvu asukoha. Järgmine kood illustreerib kursori kasutamist tasuta poega:

int * ptrInt = uus int;
* ptrInt = 12;
cout<< *ptrInt  <<'\n';

Väljund on 12.

Objekti hävitamiseks kasutage avaldist kustutamine järgmiselt:

kustuta ptrInt;

Avaldise kustutamise argument on osuti. Selle kasutamist illustreerib järgmine kood:

int * ptrInt = uus int;
* ptrInt = 12;
kustuta ptrInt;
cout<< *ptrInt <<'\n';

Väljund on 0, ja mitte midagi sellist nagu null või määratlemata. kustutab asendab asukoha väärtuse konkreetse asukohatüübi vaikeväärtusega, lubades seejärel asukoha uuesti kasutada. Int-asukoha vaikeväärtus on 0.

Ressursi uuesti kasutamine

Avaldisekategooria taksonoomias on ressursi taaskasutamine sama, mis objekti või salvestusruumi taaskasutamine. Järgmine kood illustreerib, kuidas saab tasuta poest asukohta uuesti kasutada:

int * ptrInt = uus int;
* ptrInt = 12;
cout<< *ptrInt <<'\n';
kustuta ptrInt;
cout<< *ptrInt <<'\n';
* ptrInt = 24;
cout<< *ptrInt <<'\n';

Väljund on:

12
0
24

Väärtus 12 määratakse esmalt tuvastamata asukohale. Seejärel kustutatakse asukoha sisu (teoreetiliselt objekt kustutatakse). Väärtus 24 määratakse uuesti samale asukohale.

Järgmine programm näitab, kuidas funktsiooni tagastatud täisarvuviidet taaskasutatakse:

# kaasata
nimeruumi kasutamine std;
int & fn ()

int i = 5;
int & j = i;
tagasi j;

int main ()

int & myInt = fn ();
cout<< myInt <<'\n';
myInt = 17;
cout<< myInt <<'\n';
tagastama 0;

Väljund on:

5
17

Objekt nagu i, mis on deklareeritud lokaalses ulatuses (funktsiooni ulatus), lakkab kohaliku sfääri lõpus olemast. Kuid ülaltoodud funktsioon fn () tagastab i-i viite. Selle tagastatud viite kaudu kasutab nimi, funktsioon myInt main () funktsioonis i tähistatud asukohta väärtuseks 17.

väärtus

Väärtus on avaldis, mille hindamine määrab objekti, bitivälja või funktsiooni identiteedi. Identiteet on ametlik identiteet, nagu ülaltoodud identiteet, või väärtusväärtuse viitenimi, osuti või funktsiooni nimi. Mõelge järgmisele toimivale koodile:

int myInt = 512;
int & myRef = myInt;
int * ptr = &myInt;
int fn ()

++ptr; --ptr;
tagastage myInt;

Siin on myInt väärtus; myRef on väärtusväärtus; * ptr on väärtusväärtus, kuna selle tulemus on identifitseeritav ptr-ga; ++ ptr või -ptr on lvalue avaldis, kuna selle tulemus on identifitseeritav ptr uue olekuga (aadress) ja fn on lvalue (avaldis).

Mõelge järgmisele koodisegmendile:

int a = 2, b = 8;
int c = a + 16 + b + 64;

Teises lauses on 'a' asukohal 2 ja see on identifitseeritav 'a' järgi, samuti on väärtus. B-i asukohal on 8 ja see on identifitseeritav b-ga, nii on ka väärtus. C-i asukohaks on summa ja see on identifitseeritav c-ga, nii on ka väärtus. Teises lauses on väljendite 16 ja 64 väärtused väärtused (vt allpool).

Mõelge järgmisele koodisegmendile:

char seq [5];
seq [0] = 'l', seq [1] = 'o', seq [2] = 'v', seq [3] = 'e', ​​seq [4] = '\ 0';
cout<< seq[2] <<'\n';

Väljund on 'v";

seq on massiiv. Massiivi 'v' või mõne muu sarnase väärtuse asukoht on tähistatud järjestusega [i], kus i on indeks. Niisiis, avaldis seq [i] on väärtusväärtus. seq, mis on kogu massiivi identifikaator, on samuti väärtus.

prvalue

Prvalue on avaldis, mille hindamine lähtestab objekti või bittivälja või arvutab operaatori operandi väärtuse, nagu on määratletud kontekstis, milles see ilmub.

Avalduses,

int myInt = 256;

256 on prvalue (prvalue avaldis), mis initsialiseerib myInt tuvastatud objekti. Sellele objektile pole viidatud.

Avalduses,

int && ref = 4;

4 on prvalue (prvalue avaldis), mis initsialiseerib ref. Viidatud objekti. Seda objekti ei tuvastata ametlikult. ref on näide rvalue viite avaldisest või prvalue viite avaldisest; see on nimi, kuid mitte ametlik identifikaator.

Mõelge järgmisele koodisegmendile:

int ident;
ident = 6;
int & ref = ident;

6 on eelväärtus, mis initsialiseerib identifitseeritud objekti; objektile viitab ka viide. Siin on viide lvalue ja mitte prvalue viide.

Mõelge järgmisele koodisegmendile:

int a = 2, b = 8;
int c = a + 15 + b + 63;

15 ja 63 on kumbki konstant, mis arvutab ise, saades liitmisoperaatorile operandi (bittides). Niisiis, 15 või 63 on prvalue väljend.

Iga literaal, välja arvatud stringi literaal, on prvalue (st.e., prvalue avaldis). Niisiis, sõna otseses mõttes nagu 58 või 58.53 või tõene või vale on prvalue. Sõnasõnalist saab kasutada objekti initsialiseerimiseks või arvutataks operaatori jaoks operandi väärtusena iseendale (bitti kujul). Ülaltoodud koodis initsialiseerib literaal 2 objekti a. Samuti arvutab ta ennast operatsiooni operatsiooniks määramise operaatori jaoks.

Miks pole stringi sõna otseses mõttes prvalue?? Mõelge järgmisele koodile:

char str [] = "armasta, mitte vihka";
cout << str <<'\n';
cout << str[5] <<'\n';

Väljund on:

armasta mitte vihkama
n

str tähistab kogu stringi. Niisiis, avaldis str ja mitte see, mida see identifitseerib, on väärtus. Kõiki stringi märke saab identifitseerida str [i] järgi, kus i on indeks. Avaldis str [5] ja mitte tähis, mida see identifitseerib, on väärtus. Stringi literaal on väärtus, mitte väärtus.

Järgmises lauses initsialiseerib massiiv sõna otseses mõttes objekti arr:

ptrInt ++ või ptrInt-- 

Siin on ptrInt osutaja täisarvu asukohale. Kogu avaldis, mitte selle asukoha lõplik väärtus, millele see osutab, on prvalue (avaldis). Seda seetõttu, et avaldis ptrInt ++ või ptrInt- identifitseerib selle asukoha algse esimese väärtuse, mitte sama asukoha teise lõpliku väärtuse. Teiselt poolt on -ptrInt või -ptrInt väärtus, kuna see tuvastab asukoha ainsa huvi väärtuse. Teine võimalus seda vaadata on see, et algväärtus arvutab teise lõpliku väärtuse.

Järgmise koodi teises lauses võib a või b ikkagi pidada väärtuseks:

int a = 2, b = 8;
int c = a + 15 + b + 63;

Niisiis on teise lause a või b väärtus, kuna see tuvastab objekti. See on ka prvalue, kuna see arvutatakse liitmisoperaatori operandi täisarvuni.

(uus int) ja mitte selle poolt määratud asukoht on eelväärtus. Järgmises avalduses määratakse kursoriobjektile asukoha tagasiaadress:

int * ptrInt = uus int

Siin on * ptrInt väärtus, samas kui (uus int) väärtus. Pidage meeles, et lvalue või prvalue on avaldis. (uus int) ei tuvasta ühtegi objekti. Aadressi tagastamine ei tähenda objekti tuvastamist nimega (nt ident, ülal). Rakenduses * ptrInt identifitseerib objekti tegelikult nimi ptrInt, seega on * ptrInt väärtus. Teiselt poolt on (uus int) väärtus, kuna see arvutab uue asukoha operandi väärtuse aadressiks määranguoperaatorile =.

xvalue

Täna tähistab lvalue asukohaväärtust; prvalue tähistab "puhast" rvalue (vaata, mida rvalue tähistab allpool). Täna tähistab xvalue "eXpiring" lvalue.

C ++ spetsifikatsioonist tsiteeritud xvalue määratlus on järgmine:

"Xvalue on glvalue, mis tähistab objekti või bitivälja, mille ressursse saab uuesti kasutada (tavaliselt seetõttu, et see on oma eluea lõpus). [Näide: Teatud tüüpi väljendid, mis hõlmavad väärtuse viiteid, annavad x-väärtusi, näiteks kõne funktsioonile, mille tagastustüüp on väärtuse viide, või väärtusele väärtusele viitamise tüübi lõpu näide] "

See tähendab, et nii lvalue kui prvalue võivad aeguda. Järgmine (ülalt kopeeritud) kood näitab, kuidas lvalue, * ptrInt salvestusruumi (ressurssi) pärast selle kustutamist uuesti kasutatakse.

int * ptrInt = uus int;
* ptrInt = 12;
cout<< *ptrInt <<'\n';
kustuta ptrInt;
cout<< *ptrInt <<'\n';
* ptrInt = 24;
cout<< *ptrInt <<'\n';

Väljund on:

12
0
24

Järgmine (ülalt kopeeritud) programm näitab, kuidas funktsiooni main () funktsiooni abil tagastatakse täisarvuviite salvestus, mis on funktsiooni tagastatud lvalue-viide:

# kaasata
nimeruumi kasutamine std;
int & fn ()

int i = 5;
int & j = i;
tagasi j;

int main ()

int & myInt = fn ();
cout<< myInt <<'\n';
myInt = 17;
cout<< myInt <<'\n';
tagastama 0;

Väljund on:

5
17

Kui objekt nagu i funktsioonis fn () väljub reguleerimisalast, hävitatakse see loomulikult. Sellisel juhul on i (i) salvestusruum endiselt põhifunktsioonis () taaskasutatud.

Kaks ülaltoodud koodinäidet illustreerivad väärtuste salvestamise taaskasutust. Väärtusi (väärtusi) saab salvestusruumis taaskasutada (vt hiljem).

Järgmine pakkumine xvalue kohta pärineb C ++ spetsifikatsioonist:

"Üldiselt on selle reegli tagajärg see, et nimega väärtuste viiteid käsitletakse väärtustena ja nimetamata väärtuste viiteid objektidele käsitletakse x väärtusena. Funktsioonide väärtuste viiteid käsitletakse nimiväärtusteta väärtusena.”(Vt hiljem).

Niisiis, xvalue on lvalue või prvalue, mille ressursse (salvestusruumi) saab uuesti kasutada. xvalues ​​on lvalues ​​ja prvalues ​​lõikepunkt.

Xvalue'il on rohkem kui selles artiklis käsitletud. Kuid xvalue väärib tervet artiklit iseseisvalt ja seetõttu ei käsitleta xvalue täiendavaid spetsifikatsioone.

Avaldise kategooria taksonoomia komplekt

Teine tsitaat C ++ spetsifikatsioonist:

"Märge: Ajalooliselt olid väärtused ja väärtused nn, kuna need võisid esineda ülesande vasakul ja paremal küljel (kuigi see pole enam üldiselt tõsi); glvalues ​​on "üldistatud" väärtused, prvalues ​​on "puhtad" ja xvalues ​​on "eXpiring" väärtused. Vaatamata nimedele klassifitseerivad need terminid väljendeid, mitte väärtusi. - lõpu märkus ”

Niisiis, glvalues ​​on liitväärtus lvalues ​​ja xvalues ​​ja rvalues ​​on liitväärtus xvalues ​​ja prvalues. xvalues ​​on lvalues ​​ja prvalues ​​lõikepunkt.

Praeguse seisuga on väljendikategooria taksonoomia paremini illustreeritud Venni diagrammiga järgmiselt:

Järeldus

Väärtus on avaldis, mille hindamine määrab objekti, bitivälja või funktsiooni identiteedi.

Prvalue on avaldis, mille hindamine lähtestab objekti või bittivälja või arvutab operaatori operandi väärtuse, nagu on määratletud kontekstis, milles see ilmub.

Xvalue on lvalue või prvalue koos täiendava atribuudiga, mida selle ressursse (salvestusruumi) saab uuesti kasutada.

C ++ spetsifikatsioon illustreerib avaldiskategooria taksonoomiat puudiagrammiga, mis näitab, et taksonoomias on mingi hierarhia. Praeguse seisuga ei ole taksonoomias hierarhiat, mistõttu mõned autorid kasutavad Venni diagrammi, kuna see illustreerib taksonoomiat paremini kui puudiagramm.

OpenTTD õpetus
OpenTTD on seal üks populaarsemaid ärisimulatsioonimänge. Selles mängus peate looma suurepärase transpordiettevõtte. Alustate siiski alguses umbes 190...
SuperTuxKart Linuxile
SuperTuxKart on suurepärane pealkiri, mis on loodud selleks, et tuua teie Linuxi süsteemis tasuta Mario Karti kogemus. See on päris keeruline ja lõbus...
Lahing Wesnothi õpetuse eest
Battle for Wesnoth on üks populaarsemaid avatud lähtekoodiga strateegiamänge, mida saate praegu mängida. See mäng pole mitte ainult olnud väga pikka a...