C ++

Taksonomija kategorije izraza u C ++

Taksonomija kategorije izraza u C ++

Izračun je bilo koja vrsta izračuna koja slijedi točno definirani algoritam. Izraz je niz operatora i operanda koji specificira proračun. Drugim riječima, izraz je identifikator ili doslovce ili slijed oba, kojima se pridružuju operatori.U programiranju izraz može rezultirati vrijednošću i / ili uzrokovati da se nešto dogodi. Kada rezultira vrijednošću, izraz je glvalue, rvalue, lvalue, xvalue ili prvalue. Svaka od ovih kategorija skup je izraza. Svaki skup ima definiciju i određene situacije u kojima njegovo značenje prevladava, razlikujući ga od drugog skupa. Svaki se skup naziva vrijednosnom kategorijom.

Bilješka: Vrijednost ili doslovce i dalje je izraz, pa ovi pojmovi klasificiraju izraze, a ne zapravo vrijednosti.

glvalue i rvalue dvije su podskupove iz izraza velikog skupa. glvalue postoji u dva daljnja podskupa: lvalue i xvalue. rvalue, drugi podskup za izražavanje, također postoji u dva daljnja podskupa: xvalue i prvalue. Dakle, xvalue je podskup i glvalue i rvalue: to jest, xvalue je sjecište i glvalue i rvalue. Sljedeći dijagram taksonomije, preuzet iz specifikacije C ++, ilustrira odnos svih skupova:

prvalue, xvalue i lvalue su vrijednosti primarne kategorije. glvalue je unija lvalues ​​i xvalues, dok je rvalues ​​unija xvalues ​​i prvalues.

Potrebno vam je osnovno znanje na jeziku C ++ da biste razumjeli ovaj članak; također trebate znanje o opsegu u C++.

Sadržaj članka

Osnove

Da biste stvarno razumjeli taksonomiju kategorija izraza, prvo se morate sjetiti ili znati sljedeće osnovne značajke: mjesto i objekt, pohranu i resurs, inicijalizacija, identifikator i referenca, reference lvalue i rvalue, pokazivač, slobodno spremanje i ponovna upotreba resurs.

Mjesto i objekt

Razmotrite sljedeću izjavu:

int ident;

Ovo je deklaracija koja identificira mjesto u memoriji. Mjesto je određeni skup uzastopnih bajtova u memoriji. Mjesto se može sastojati od jednog bajta, dva bajta, četiri bajta, šezdeset četiri bajta itd. Mjesto cijelog broja za 32-bitni stroj je četiri bajta. Također, mjesto se može identificirati pomoću identifikatora.

U gornjoj deklaraciji, mjesto nema nikakav sadržaj. To znači da nema nikakvu vrijednost, jer je sadržaj vrijednost. Dakle, identifikator identificira mjesto (mali kontinuirani prostor). Kada se lokaciji da određeni sadržaj, identifikator tada identificira i lokaciju i sadržaj; to jest, identifikator tada identificira i mjesto i vrijednost.

Razmotrite sljedeće izjave:

int ident1 = 5;
int ident2 = 100;

Svaka od ovih izjava je izjava i definicija. Prvi identifikator ima vrijednost (sadržaj) 5, a drugi identifikator ima vrijednost 100. U 32-bitnom stroju svako od ovih mjesta duga je četiri bajta. Prvi identifikator identificira i mjesto i vrijednost. Drugi identifikator također identificira oboje.

Objekt je imenovano područje pohrane u memoriji. Dakle, objekt je ili mjesto bez vrijednosti ili mjesto s vrijednošću.

Pohrana predmeta i resursi

Mjesto za objekt naziva se i spremište ili resurs objekta.

Inicijalizacija

Razmotrite sljedeći segment koda:

int ident;
ident = 8;

Prvi redak objavljuje identifikator. Ova deklaracija pruža mjesto (pohranu ili resurs) za cjelobrojni objekt, identificirajući ga s imenom, ident. Sljedeći redak stavlja vrijednost 8 (u bitovima) na mjesto identificirano identom. Stavljanje ove vrijednosti je inicijalizacija.

Sljedeća izjava definira vektor sa sadržajem, 1, 2, 3, 4, 5, identificiran vtr:

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

Ovdje se inicijalizacija s 1, 2, 3, 4, 5 vrši u istoj izjavi definicije (deklaracije). Operator dodjele se ne koristi. Sljedeća izjava definira niz sa sadržajem 1, 2, 3, 4, 5:

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

Ovoga puta za inicijalizaciju je korišten operator dodjele.

Identifikator i referenca

Razmotrite sljedeći segment koda:

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

Izlaz je:

4 4 4

ident je identifikator, dok su ref1 i ref2 reference; upućuju na isto mjesto. Referenca je sinonim za identifikator. Uobičajeno su ref1 i ref2 različita imena jednog objekta, dok je ident identifikator istog objekta. Međutim, ident se i dalje može nazvati imenom objekta, što znači da ident, ref1 i ref2 imenuju isto mjesto.

Glavna razlika između identifikatora i reference je u tome što se, kada se proslijedi kao argument funkciji, ako se proslijedi pomoću identifikatora, napravi kopija za identifikator u funkciji, dok se ako se proslijedi referencom, isto mjesto koristi unutar funkcija. Dakle, prolazak pored identifikatora završava na dva mjesta, dok prolazak pored reference završava na istom mjestu.

Referenca lvalue i Referenca rvalue

Uobičajeni način stvaranja reference je sljedeći:

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

Pohrana (resurs) se prvo locira i identificira (s imenom poput ident), a zatim se napravi referenca (s imenom kao što je ref). Kada se funkcija prosljeđuje kao argument, u funkciji će se napraviti kopija identifikatora, dok će se u slučaju reference koristiti (na koje se odnosi) izvorno mjesto u funkciji.

Danas je moguće samo imati referencu bez da je identificirate. To znači da je moguće prvo stvoriti referencu bez da imate identifikator mjesta. Ovdje se koristi &&, kao što je prikazano u sljedećoj izjavi:

int && ref = 4;

Ovdje nema prethodne identifikacije. Da biste pristupili vrijednosti objekta, jednostavno upotrijebite ref kao što biste koristili gore navedeni ident.

S && deklaracijom ne postoji mogućnost prosljeđivanja argumenta funkciji pomoću identifikatora. Jedini je izbor proći referencom. U ovom se slučaju unutar funkcije koristi samo jedno mjesto, a ne drugo kopirano mjesto kao kod identifikatora.

Referentna deklaracija s & naziva se lvalue reference. Referentna deklaracija s && naziva se rvalue reference, koja je ujedno i referenca prvalue (vidi dolje).

Pokazivač

Razmotrite sljedeći kod:

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

Izlaz je 5.

Ovdje je ptdInt identifikator poput identiteta gore. Ovdje su dva objekta (lokacije) umjesto jednog: šiljati objekt, ptdInt identificiran ptdInt, i objekt pokazivača, ptrInt identificiran ptrInt. & ptdInt vraća adresu usmjerenog objekta i stavlja je kao vrijednost u objekt pokazivača ptrInt. Da biste vratili (pribavili) vrijednost usmjerenog objekta, upotrijebite identifikator pokazivačkog objekta, kao u “* ptrInt”.

Bilješka: ptdInt je identifikator, a ne referenca, dok je prethodno spomenuto ime, ref, referenca.

Drugi i treći redak u gornjem kodu mogu se svesti na jedan redak, što dovodi do sljedećeg koda:

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

Bilješka: Kada se pokazivač poveća, on usmjerava na sljedeće mjesto, što nije dodatak vrijednosti 1. Kada se pokazivač smanji, on usmjerava na prethodno mjesto, što nije oduzimanje vrijednosti 1.

Besplatna trgovina

Operativni sustav dodjeljuje memoriju za svaki pokrenut program. Memorija koja nije dodijeljena nijednom programu poznata je kao besplatna trgovina. Izraz koji vraća mjesto za cijeli broj iz besplatne trgovine je:

novi međ

To vraća mjesto za cijeli broj koji nije identificiran. Sljedeći kod ilustrira kako koristiti pokazivač u besplatnoj trgovini:

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

Izlaz je 12.

Da biste uništili objekt, upotrijebite izraz delete na sljedeći način:

izbriši ptrInt;

Argument izraza delete je pokazivač. Sljedeći kod ilustrira njegovu upotrebu:

int * ptrInt = novo int;
* ptrInt = 12;
izbriši ptrInt;
cout<< *ptrInt <<'\n';

Izlaz je 0, a ne nešto poput nule ili nedefiniranog. delete zamjenjuje vrijednost lokacije sa zadanom vrijednošću određene vrste lokacije, a zatim omogućuje lokaciju za ponovnu upotrebu. Zadana vrijednost za int lokaciju je 0.

Ponovna upotreba resursa

U taksonomiji kategorija izraza, ponovna upotreba resursa isto je što i ponovna upotreba mjesta ili pohrane za objekt. Sljedeći kod ilustrira kako se lokacija iz besplatne trgovine može ponovno upotrijebiti:

int * ptrInt = novo int;
* ptrInt = 12;
cout<< *ptrInt <<'\n';
izbriši ptrInt;
cout<< *ptrInt <<'\n';
* ptrInt = 24;
cout<< *ptrInt <<'\n';

Izlaz je:

12
0
24

Vrijednost 12 prvo se dodjeljuje neidentificiranom mjestu. Tada se sadržaj lokacije briše (u teoriji se objekt briše). Vrijednost 24 ponovno se dodjeljuje istom mjestu.

Sljedeći program pokazuje kako se ponovno koristi cjelobrojna referenca koju vraća funkcija:

#include
pomoću prostora imena std;
int & fn ()

int i = 5;
int & j = i;
povratak j;

int main ()

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

Izlaz je:

5
17

Objekt kao što je i, deklariran u lokalnom opsegu (opseg funkcije), prestaje postojati na kraju lokalnog opsega. Međutim, funkcija fn () gore vraća referencu i. Kroz ovu vraćenu referencu, ime, myInt u funkciji main (), ponovno koristi mjesto identificirano i za vrijednost 17.

Vrijednost

Lvalue je izraz čija procjena određuje identitet objekta, bit-polja ili funkcije. Identitet je službeni identitet kao što je gore navedeni ident, ili naziv reference lvalue, pokazivač ili naziv funkcije. Razmotrite sljedeći kod koji radi:

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

++ptr; --ptr;
return myInt;

Ovdje je myInt vrijednost; myRef je referentni izraz lvalue; * ptr je izraz lvalue jer se njegov rezultat može identificirati s ptr; ++ ptr ili -ptr je izraz lvalue jer se njegov rezultat može identificirati s novim stanjem (adresom) ptr, a fn je lvalue (izraz).

Razmotrite sljedeći segment koda:

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

U drugoj izjavi, mjesto za 'a' ima 2 i može se identificirati sa 'a', kao i lvalue. Mjesto za b ima 8, a b ga je moguće prepoznati, a isto tako i vrijednost. Mjesto za c imat će zbroj, a prepoznatljivo je s c, a isto tako i lvalue. U drugoj izjavi izrazi ili vrijednosti 16 i 64 su rvalue (vidi dolje).

Razmotrite sljedeći segment koda:

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

Izlaz je 'v';

seq je niz. Mjesto za 'v' ili bilo koju sličnu vrijednost u polju identificirano je pomoću seq [i], gdje je i indeks. Dakle, izraz, seq [i], je izraz vrijednosti. seq, koji je identifikator cijelog niza, također je vrijednost.

prvalue

Prvalue je izraz čija evaluacija inicijalizira objekt ili bitno polje ili izračunava vrijednost operanda operatora, kako je određeno kontekstom u kojem se pojavljuje.

U izjavi,

int myInt = 256;

256 je prvalue (izraz prvalue) koja inicijalizira objekt identificiran myInt. Ovaj objekt nije referenciran.

U izjavi,

int && ref = 4;

4 je prva vrijednost (izraz prvalue) koja inicijalizira objekt na koji se ref. Ovaj objekt nije službeno identificiran. ref je primjer referentnog izraza rvalue ili referentnog izraza prvalue; to je ime, ali ne i službeni identifikator.

Razmotrite sljedeći segment koda:

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

6 je prva vrijednost koja inicijalizira objekt identificiran identom; na objekt se referira i ref. Ovdje je referenca referenca lvalue, a ne referenca prvalue.

Razmotrite sljedeći segment koda:

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

15 i 63 su svaka konstanta koja izračunava za sebe, stvarajući operand (u bitovima) za operator zbrajanja. Dakle, 15 ili 63 je izraz prve vrijednosti.

Bilo koji doslovni, osim doslovnog niza, prva je vrijednost (tj.e., izraz prve vrijednosti). Dakle, doslovno kao što je 58 ili 58.53, ili točno ili netačno, prva je vrijednost. Doslovce se može koristiti za inicijalizaciju objekta ili bi izračunao za sebe (u neki drugi oblik u bitovima) kao vrijednost operanda za operatora. U gornjem kodu, doslovni 2 inicijalizira objekt, a. Također se izračunava kao operand operatora dodjele.

Zašto doslovni niz nije prva vrijednost? Razmotrite sljedeći kod:

char str [] = "ljubav ne mržnja";
cout << str <<'\n';
cout << str[5] <<'\n';

Izlaz je:

ljubav ne mržnja
n

str identificira cijeli niz. Dakle, izraz str, a ne ono što identificira, vrijednost je. Svaki znak u nizu može se identificirati pomoću str [i], gdje je i indeks. Izraz str [5], a ne znak koji identificira, vrijednost je. Znakovni niz je vrijednost lv, a ne prva vrijednost.

U sljedećoj izjavi, literal niza inicijalizira objekt, arr:

ptrInt ++ ili ptrInt-- 

Ovdje je ptrInt pokazivač na cijelobrojno mjesto. Cijeli izraz, a ne konačna vrijednost mjesta na koje upućuje, prva je vrijednost (izraz). To je zato što izraz, ptrInt ++ ili ptrInt-, identificira izvornu prvu vrijednost svog mjesta, a ne drugu konačnu vrijednost istog mjesta. S druge strane, -ptrInt ili -ptrInt je vrijednost, jer identificira jedinu vrijednost interesa na mjestu. Drugi način gledanja na to je da izvorna vrijednost izračunava drugu konačnu vrijednost.

U drugoj izjavi sljedećeg koda, a ili b i dalje se mogu smatrati prvom vrijednošću:

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

Dakle, a ili b u drugoj izjavi vrijednost je jer identificira objekt. Također je prva vrijednost jer izračunava cijeli broj operanda za operator zbrajanja.

(novi int), a ne mjesto koje uspostavlja prva je vrijednost. U sljedećem je iskazu povratna adresa lokacije dodijeljena pokazivačkom objektu:

int * ptrInt = novo int

Ovdje je * ptrInt vrijednost, dok je (new int) prva vrijednost. Zapamtite, lvalue ili prvalue je izraz. (new int) ne identificira nijedan objekt. Vraćanje adrese ne znači identificiranje objekta s imenom (kao što je ident, gore). U * ptrInt je ime, ptrInt, ono što stvarno identificira objekt, tako da je * ptrInt vrijednost. S druge strane, (new int) je prva vrijednost, jer izračunava novo mjesto na adresu vrijednosti operanda za operator dodjeljivanja =.

xvalue

Danas lvalue znači vrijednost lokacije; prvalue znači "čista" rvalue (pogledajte što rvalue znači u nastavku). Danas xvalue znači "eXpiring" lvalue.

Definicija xvalue, citirana iz specifikacije C ++, je kako slijedi:

„Xvalue je glvalue koja označava objekt ili bitno polje čiji se resursi mogu ponovno koristiti (obično zato što je pri kraju svog životnog vijeka). [Primjer: Određene vrste izraza koji uključuju reference rvalue daju xvalues, poput poziva na funkciju čiji je povratni tip referenca rvalue ili premještanje na rvalue referencu tipa-kraj primjera] "

To znači da lvalue i prvalue mogu isteći. Sljedeći kod (kopiran odozgo) pokazuje kako se pohrana (resurs) lvalue, * ptrInt ponovno koristi nakon što je izbrisana.

int * ptrInt = novo int;
* ptrInt = 12;
cout<< *ptrInt <<'\n';
izbriši ptrInt;
cout<< *ptrInt <<'\n';
* ptrInt = 24;
cout<< *ptrInt <<'\n';

Izlaz je:

12
0
24

Sljedeći program (kopiran odozgo) pokazuje kako se pohrana cjelobrojne reference, koja je referenca lvalue koju vraća funkcija, ponovno koristi u funkciji main ():

#include
pomoću prostora imena std;
int & fn ()

int i = 5;
int & j = i;
povratak j;

int main ()

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

Izlaz je:

5
17

Kad objekt kao što je i u funkciji fn () izlazi iz opsega, on se prirodno uništava. U ovom je slučaju pohrana i još uvijek ponovno upotrijebljena u funkciji main ().

Gornja dva uzorka koda ilustriraju ponovnu upotrebu pohrane lvalues. Moguće je imati ponovno korištenje spremišta vrijednosti (vrijednosti) (vidi kasnije).

Sljedeći citat koji se odnosi na xvalue potječe iz specifikacije C ++:

„Općenito, učinak ovog pravila je da se imenovane rvalue reference tretiraju kao lvalues, a neimenovane rvalue reference na objekte kao xvalues. reference rvalue na funkcije tretiraju se kao lvalues ​​bez obzira jesu li imenovane ili ne." (vidimo se kasnije).

Dakle, xvalue je lvalue ili prvalue čiji se resursi (pohrana) mogu ponovno koristiti. xvalues ​​je presječni skup lvalues ​​i prvalues.

Xvalue je više od onoga o čemu je riječ u ovom članku. Međutim, xvalue zaslužuje cijeli članak sam za sebe, pa se u ovom članku ne razmatraju dodatne specifikacije za xvalue.

Skup taksonomije kategorije izraza

Još jedan citat iz specifikacije C ++:

Bilješka: Povijesno gledano, vrijednosti i vrijednosti su bile takozvane jer su se mogle pojaviti na lijevoj i desnoj strani zadatka (iako to općenito više nije točno); vrijednosti su "generalizirane" vrijednosti, vrijednosti su "čiste" vrijednosti, a vrijednosti su "istekle" vrijednosti. Unatoč imenima, ti pojmovi klasificiraju izraze, a ne vrijednosti. - završna napomena "

Dakle, glvalues ​​je skup unija lvalues ​​i xvalues, a rvalues ​​je unija skup xvalues ​​i prvalues. xvalues ​​je presječni skup lvalues ​​i prvalues.

Od sada je taksonomija kategorija izraza bolje ilustrirana Vennovim dijagramom kako slijedi:

Zaključak

Lvalue je izraz čija procjena određuje identitet objekta, bit-polja ili funkcije.

Prvalue je izraz čija evaluacija inicijalizira objekt ili bitno polje ili izračunava vrijednost operanda operatora, kako je određeno kontekstom u kojem se pojavljuje.

Xvalue je lvalue ili prvalue, s dodatnim svojstvom da se njegovi resursi (pohrana) mogu ponovno koristiti.

Specifikacija C ++ ilustrira taksonomiju kategorija izraza dijagramom stabla, naznačujući da u taksonomiji postoji neka hijerarhija. Od sada u taksonomiji ne postoji hijerarhija, pa se neki autori koriste Venovim dijagramom, jer taksonomiju ilustrira bolje od dijagrama stabla.

Kako koristiti GameConqueror Cheat Engine u Linuxu
Članak pokriva vodič o korištenju GameConqueror varalice u Linuxu. Mnogi korisnici koji igraju igre na sustavu Windows često koriste aplikaciju "Cheat...
Najbolji emulatori igraće konzole za Linux
Ovaj će članak navesti popularni softver za emulaciju igraće konzole dostupan za Linux. Emulacija je sloj kompatibilnosti softvera koji oponaša hardve...
Najbolji Linux Distros za igre na sreću 2021. godine
Linux operativni sustav daleko je prevalio svoj izvorni, jednostavni izgled zasnovan na poslužitelju. Ovaj se OS posljednjih godina izuzetno poboljšao...