C ++

Izteiksmes kategorijas taksonomija C ++

Izteiksmes kategorijas taksonomija C ++

Aprēķins ir jebkura veida aprēķins, kas seko precīzi definētam algoritmam. Izteiksme ir operatoru un operandu secība, kas norāda aprēķinu. Citiem vārdiem sakot, izteiksme ir identifikators vai burts, vai abu secība, ko savieno operatori.Programmējot izteiksme var izraisīt vērtību un / vai izraisīt kādu notikumu. Kad tā rezultātā iegūst vērtību, izteiksme ir glvalue, rvalue, lvalue, xvalue vai prvalue. Katra no šīm kategorijām ir izteicienu kopums. Katram kopumam ir definīcija un īpašas situācijas, kurās dominē tā nozīme, atšķirot to no citas kopas. Katru kopu sauc par vērtību kategoriju.

Piezīme: Vērtība vai burtisks joprojām ir izteiksme, tāpēc šie termini klasificē izteicienus, nevis patiesībā vērtības.

glvalue un rvalue ir divas apakškopas no lielās kopas izteiksmes. glvalue pastāv vēl divās apakškopās: lvalue un xvalue. rvalue, otra izteiksmes apakškopa, pastāv arī vēl divās apakškopās: xvalue un prvalue. Tātad, xvalue ir gan glvalue, gan rvalue apakškopa: tas ir, xvalue ir gan glvalue, gan rvalue krustojums. Šī taksonomijas diagramma, kas ņemta no C ++ specifikācijas, parāda visu kopu saistību:

prvalue, xvalue un lvalue ir primārās kategorijas vērtības. glvalue ir vērtību un xvalues ​​savienojums, savukārt rvalues ​​ir xvalues ​​un prvalues ​​savienojums.

Lai saprastu šo rakstu, jums nepieciešamas pamatzināšanas C ++ valodā; jums ir nepieciešamas arī zināšanas par darbības jomu C++.

Raksta saturs

Pamati

Lai patiešām saprastu izteiksmes kategorijas taksonomiju, vispirms jāatgādina vai jāzina šādas pamata funkcijas: atrašanās vieta un objekts, krātuve un resurss, inicializācija, identifikators un atsauce, atsauces vērtības un vērtības, rādītājs, bezmaksas veikals un atkārtota resurss.

Atrašanās vieta un objekts

Apsveriet šādu paziņojumu:

int ident;

Šī ir deklarācija, kas identificē vietu atmiņā. Atrašanās vieta ir noteikts secīgu baitu kopums atmiņā. Atrašanās vieta var sastāvēt no viena baita, diviem, četriem, sešdesmit četriem baitiem utt. Vesela skaitļa atrašanās vieta 32 bitu mašīnai ir četri baiti. Arī atrašanās vietu var identificēt pēc identifikatora.

Iepriekš minētajā deklarācijā atrašanās vietai nav satura. Tas nozīmē, ka tam nav nekādas vērtības, jo vērtība ir vērtība. Tātad identifikators identificē atrašanās vietu (nelielu nepārtrauktu atstarpi). Kad atrašanās vietai tiek piešķirts noteikts saturs, identifikators identificē gan atrašanās vietu, gan saturu; tas ir, identifikators pēc tam identificē gan atrašanās vietu, gan vērtību.

Apsveriet šādus apgalvojumus:

int ident1 = 5;
int ident2 = 100;

Katrs no šiem apgalvojumiem ir deklarācija un definīcija. Pirmajam identifikatoram ir vērtība (saturs) 5, bet otrajam - 100. 32 bitu mašīnā katra no šīm vietām ir četru baitu gara. Pirmais identifikators identificē gan atrašanās vietu, gan vērtību. Otrais identifikators identificē arī abus.

Objekts ir nosaukts atmiņas reģions. Tātad objekts ir vai nu vieta bez vērtības, vai arī vieta ar vērtību.

Objekta krātuve un resurss

Objekta atrašanās vietu sauc arī par objekta krātuvi vai resursu.

Inicializēšana

Apsveriet šādu koda segmentu:

int ident;
ident = 8;

Pirmajā rindā ir norādīts identifikators. Šī deklarācija nodrošina objekta atrašanās vietu (krātuvi vai resursu), identificējot to ar nosaukumu, ident. Nākamajā rindā vērtība 8 (bitos) tiek ievietota vietā, kuru identificē ident. Šīs vērtības ievietošana ir inicializācija.

Šis apgalvojums definē vektoru ar saturu 1, 2, 3, 4, 5, kuru identificē ar vtr:

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

Šeit inicializēšana ar 1, 2, 3, 4, 5 tiek veikta tajā pašā definīcijas (deklarācijas) paziņojumā. Piešķiršanas operators netiek izmantots. Šis paziņojums nosaka masīvu ar saturu 1, 2, 3, 4, 5:

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

Šoreiz inicializēšanai tika izmantots piešķiršanas operators.

Identifikators un atsauce

Apsveriet šādu koda segmentu:

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

Rezultāts ir:

4 4 4

ident ir identifikators, savukārt ref1 un ref2 ir atsauces; tie norāda to pašu vietu. Atsauce ir identifikatora sinonīms. Parasti ref1 un ref2 ir dažādi viena objekta nosaukumi, bet ident ir tā paša objekta identifikators. Tomēr ident joprojām var saukt par objekta nosaukumu, kas nozīmē ident, ref1 un ref2 nosauc to pašu vietu.

Galvenā atšķirība starp identifikatoru un atsauci ir tāda, ka, nododot to kā argumentu funkcijai, ja to nodod ar identifikatoru, funkcijā esošajam identifikatoram tiek kopēts, savukārt, ja tas tiek nodots ar atsauci, tajā pašā vietā tiek izmantota funkciju. Tātad, ejot garām identifikatoram, tiek iegūtas divas vietas, bet garāmejot ar atsauci - viena un tā pati vieta.

lvalue Reference un rvalue Reference

Normāls veids, kā izveidot atsauci, ir šāds:

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

Vispirms tiek atrasta un identificēta krātuve (resurss) (ar nosaukumu, piemēram, ident), un pēc tam tiek izveidota atsauce (ar nosaukumu, piemēram, atsauce). Nododot kā argumentu funkcijai, funkcijā tiks izveidota identifikatora kopija, savukārt atsauces gadījumā funkcijā tiks izmantota (norādīta) sākotnējā atrašanās vieta.

Šodien ir iespējams vienkārši iegūt atsauci, to nenosakot. Tas nozīmē, ka vispirms ir iespējams izveidot atsauci bez vietas identifikatora. Šajā gadījumā tiek izmantots &&, kā parādīts šajā paziņojumā:

int && ref = 4;

Šeit nav iepriekšējas identifikācijas. Lai piekļūtu objekta vērtībai, vienkārši izmantojiet ref, kā jūs izmantotu iepriekš minēto identifikatoru.

Izmantojot && deklarāciju, nav iespējams argumentu nodot funkcijai pēc identifikatora. Vienīgā izvēle ir nodot atsauci. Šajā gadījumā funkcijā tiek izmantota tikai viena atrašanās vieta, nevis otrā kopētā atrašanās vieta kā ar identifikatoru.

Atsauces deklarāciju ar & sauc par vērtību lvalue. Atsauces deklarāciju ar && sauc par atsauces vērtību, kas ir arī atsauces atsauce (skat. Zemāk).

Rādītājs

Apsveriet šādu kodu:

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

Rezultāts ir 5.

Šeit ptdInt ir identifikators, piemēram, iepriekš minētais. Šeit ir divi objekti (atrašanās vietas), nevis viens: smails objekts, ptdInt identificēts ar ptdInt, un rādītāja objekts ptrInt, ko identificējis ptrInt. & ptdInt atgriež smailā objekta adresi un ievieto to kā vērtību rādītāja ptrInt objektā. Lai atgrieztu (iegūtu) smailā objekta vērtību, izmantojiet rādītāja objekta identifikatoru, kā norādīts sadaļā “* ptrInt”.

Piezīme: ptdInt ir identifikators, nevis atsauce, savukārt iepriekš minētais nosaukums ref ir atsauce.

Iepriekšējā koda otro un trešo rindu var samazināt līdz vienai rindai, kā rezultātā tiek iegūts šāds kods:

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

Piezīme: Kad rādītājs tiek palielināts, tas norāda uz nākamo vietu, kas nav vērtības 1 papildinājums. Kad rādītājs tiek samazināts, tas norāda uz iepriekšējo vietu, kas nav 1. vērtības atņemšana.

Bezmaksas veikals

Operētājsistēma piešķir atmiņu katrai darbojošajai programmai. Atmiņa, kas nav piešķirta nevienai programmai, tiek dēvēta par bezmaksas veikalu. Izteiksme, kas atgriež vesela skaitļa atrašanās vietu no bezmaksas veikala, ir:

jauns int

Tas atgriež neatpazīta vesela skaitļa atrašanās vietu. Šis kods parāda, kā izmantot rādītāju ar bezmaksas veikalu:

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

Rezultāts ir 12.

Lai iznīcinātu objektu, izmantojiet izteiksmes dzēšanu šādi:

dzēst ptrInt;

Izteikuma dzēšanas arguments ir rādītājs. Šis kods parāda tā izmantošanu:

int * ptrInt = jauns int;
* ptrInt = 12;
dzēst ptrInt;
cout<< *ptrInt <<'\n';

Rezultāts ir 0, un ne par ko līdzīgu null vai nenoteiktam. Dzēst aizstāj vietas vērtību ar noklusējuma vērtību konkrētam atrašanās vietas tipam, pēc tam ļauj atrašanās vietu atkārtoti izmantot. Int atrašanās vietas noklusējuma vērtība ir 0.

Resursa atkārtota izmantošana

Izteiksmes kategorijas taksonomijā resursa atkārtota izmantošana ir tāda pati kā objekta atrašanās vietas vai krātuves atkārtota izmantošana. Šis kods parāda, kā atrašanās vietu no bezmaksas veikala var atkārtoti izmantot:

int * ptrInt = jauns int;
* ptrInt = 12;
cout<< *ptrInt <<'\n';
dzēst ptrInt;
cout<< *ptrInt <<'\n';
* ptrInt = 24;
cout<< *ptrInt <<'\n';

Rezultāts ir:

12
0
24

Neidentificētajai vietai vispirms tiek piešķirta vērtība 12. Pēc tam atrašanās vietas saturs tiek izdzēsts (teorētiski objekts tiek izdzēsts). Vērtība 24 tiek atkārtoti piešķirta tai pašai vietai.

Šī programma parāda, kā funkcijas atgriezta vesela skaitļa atsauce tiek atkārtoti izmantota:

# iekļaut
izmantojot nosaukumvietu std;
int & fn ()

int i = 5;
int & j = i;
atgriešanās j;

int main ()

int & myInt = fn ();
cout<< myInt <<'\n';
myInt = 17;
cout<< myInt <<'\n';
atgriešanās 0;

Rezultāts ir:

5
17

Tāds objekts kā i, kas deklarēts lokālā darbības jomā (funkciju tvērums), pārstāj eksistēt lokālās darbības jomas beigās. Tomēr funkcija fn () iepriekš atgriež atsauci uz i. Izmantojot šo atgriezto atsauci, nosaukums myInt main () funkcijā atkārtoti izmanto i identificēto vietu vērtībai 17.

vērtība

Lvalue ir izteiksme, kuras novērtējums nosaka objekta, bitu lauka vai funkcijas identitāti. Identitāte ir oficiāla identitāte, piemēram, identitāte iepriekš, vai vērtības atsauces nosaukums, rādītājs vai funkcijas nosaukums. Apsveriet šādu derīgo kodu:

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

++ptr; --ptr;
atgriezt myInt;

Šeit myInt ir vērtība; myRef ir vērtības atsauces izteiksme; * ptr ir vērtības izteiksme, jo tā rezultāts ir identificējams ar ptr; ++ ptr vai -ptr ir lvalue izteiksme, jo tā rezultāts ir identificējams ar ptr jauno stāvokli (adresi), un fn ir lvalue (izteiksme).

Apsveriet šādu koda segmentu:

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

Otrajā paziņojumā “a” atrašanās vietai ir 2 un to var identificēt ar “a”, tāpat arī vērtību. Vietai b ir 8, un to var identificēt ar b, un tā ir arī vērtība. Vietai c būs summa, un to varēs identificēt ar c, un tā ir arī vērtība. Otrajā paziņojumā izteiksmes vai vērtības 16 un 64 ir vērtības (skatīt zemāk).

Apsveriet šādu koda segmentu:

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

Rezultāts ir 'v";

sek ir masīvs. Vietu “v” vai jebkurai līdzīgai masīva vērtībai identificē ar seku [i], kur i ir indekss. Tātad izteiksme seq [i] ir vērtības izteiksme. seq, kas ir visa masīva identifikators, arī ir vērtība.

prvalue

Prvalue ir izteiksme, kuras novērtējums inicializē objektu vai bitu lauku vai aprēķina operatora operanda vērtību, kā norādīts kontekstā, kurā tā parādās.

Paziņojumā,

int myInt = 256;

256 ir prvalue (prvalue izteiksme), kas inicializē myInt identificēto objektu. Uz šo objektu nav atsauces.

Paziņojumā,

int && ref = 4;

4 ir prvalue (prvalue izteiksme), kas inicializē objektu, uz kuru atsaucas atsauce. Šis objekts nav oficiāli identificēts. ref ir rvalue atsauces izteiksmes vai prvalue atsauces izteiksmes piemērs; tas ir nosaukums, bet ne oficiāls identifikators.

Apsveriet šādu koda segmentu:

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

6 ir sākotnējā vērtība, kas inicializē objektu, kas identificēts ar identitāti; uz objektu atsaucas arī atsauce. Šeit atsauce ir lvalue atsauce, nevis prvalue atsauce.

Apsveriet šādu koda segmentu:

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

15 un 63 ir konstante, kas aprēķina pati sevi, veidojot operantu (bitos) pievienošanas operatoram. Tātad 15 vai 63 ir prvalue izteiksme.

Jebkurš literārs, izņemot virknes literālu, ir prvalue (t.i.e., izteiksmes izteiksme). Tātad, burtiskais, piemēram, 58 vai 58.53 vai patiesa vai nepatiesa ir prvalue. Burtnieku var izmantot, lai inicializētu objektu, vai arī tas pats sev aprēķinātu (citā formā ar bitiem) kā operanda vērtību operatoram. Iepriekš minētajā kodā burtiskais 2 inicializē objektu, a. Tas arī aprēķina sevi kā operanda piešķiršanas operatoram.

Kāpēc virknes burtisks nav prvalue? Apsveriet šādu kodu:

char str [] = "nemīlēties ar mīlestību";
cout << str <<'\n';
cout << str[5] <<'\n';

Rezultāts ir:

mīlu naidu
n

str identificē visu virkni. Tātad izteiksme str un nevis tas, ko tā identificē, ir vērtība. Katru rakstzīmi virknē var identificēt ar str [i], kur i ir indekss. Izteiksme str [5], nevis raksturs, kuru tā identificē, ir vērtība. Virknes literālis ir lvalue, nevis prvalue.

Šajā paziņojumā masīvs burtiski inicializē objektu arr:

ptrInt ++ vai ptrInt-- 

Šeit ptrInt ir rādītājs uz veselu skaitļu atrašanās vietu. Visa izteiksme, nevis tās atrašanās vietas galīgā vērtība, uz kuru tā norāda, ir prvalue (izteiksme). Tas ir tāpēc, ka izteiksme ptrInt ++ vai ptrInt- identificē sākotnējo tās atrašanās vietas pirmo vērtību, nevis tās pašas vietas otro galīgo vērtību. No otras puses, -ptrInt vai -ptrInt ir vērtība, jo tā identificē vienīgo intereses vērtību atrašanās vietā. Vēl viens veids, kā to aplūkot, ir tas, ka sākotnējā vērtība aprēķina otro galīgo vērtību.

Šī koda otrajā teikumā a vai b joprojām var uzskatīt par prvalu:

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

Tātad otrā teikuma a vai b vērtība ir vērtība, jo tā identificē objektu. Tā ir arī sākotnējā vērtība, jo tā aprēķina pievienošanas operatora operanda veselu skaitli.

(new int), un nevis tā noteiktā vieta ir sākotnējā vērtība. Šajā paziņojumā atrašanās vietas atgriešanās adrese tiek piešķirta rādītāja objektam:

int * ptrInt = jauns int

Šeit * ptrInt ir lvalue, savukārt (new int) ir prvalue. Atcerieties, ka lvalue vai prvalue ir izteiksme. (new int) nenosaka nevienu objektu. Atgriežot adresi, tas nenozīmē objekta identificēšanu ar nosaukumu (piemēram, ident, iepriekš). Programmā * ptrInt nosaukums ptrInt ir tas, kas patiesībā identificē objektu, tāpēc * ptrInt ir vērtība. No otras puses, (new int) ir sākotnējā vērtība, jo tā aprēķina jaunu atrašanās vietu operanda vērtības adresei piešķiršanas operatoram =.

xvalue

Mūsdienās lvalue nozīmē Location Value; prvalue nozīmē “tīra” rvalue (zemāk skatiet, ko nozīmē rvalue). Šodien xvalue nozīmē “eXpiring” lvalue.

Xvalue definīcija, kas citēta no C ++ specifikācijas, ir šāda:

“Xvalue ir glvalue, kas apzīmē objektu vai bitu lauku, kura resursus var atkārtoti izmantot (parasti tāpēc, ka tas ir tuvu sava mūža beigām). [Piemērs: Noteikti izteicienu veidi, kas saistīti ar atsauces vērtībām, dod x vērtības, piemēram, izsaukums funkcijai, kuras atgriešanās tips ir atsauces vērtība vai nodošana vērtības atsauces tipa beigu piemēram] ”

Tas nozīmē, ka var beigties gan lvalue, gan prvalue derīguma termiņš. Šis kods (nokopēts no augšas) parāda, kā lvalue * ptrInt krātuve (resurss) tiek atkārtoti izmantota pēc tās dzēšanas.

int * ptrInt = jauns int;
* ptrInt = 12;
cout<< *ptrInt <<'\n';
dzēst ptrInt;
cout<< *ptrInt <<'\n';
* ptrInt = 24;
cout<< *ptrInt <<'\n';

Rezultāts ir:

12
0
24

Šī programma (nokopēta no augšas) parāda, kā vesela skaitļa atsauces krātuve, kas ir funkcijas atgriezta vērtības vērtība, tiek atkārtoti izmantota galvenajā () funkcijā:

# iekļaut
izmantojot nosaukumvietu std;
int & fn ()

int i = 5;
int & j = i;
atgriešanās j;

int main ()

int & myInt = fn ();
cout<< myInt <<'\n';
myInt = 17;
cout<< myInt <<'\n';
atgriešanās 0;

Rezultāts ir:

5
17

Kad objekts, piemēram, i fn () funkcijā, iziet no darbības jomas, tas dabiski tiek iznīcināts. Šajā gadījumā i krātuve joprojām ir atkārtoti izmantota galvenajā () funkcijā.

Iepriekš minētie divi kodu paraugi ilustrē vērtību vērtības glabāšanas atkārtotu izmantošanu. Ir iespējams atkārtoti izmantot sākotnējās vērtības (vērtības) krātuvē (skatīt vēlāk).

Šis citāts par xvalue ir no C ++ specifikācijas:

“Parasti šī noteikuma rezultāts ir tāds, ka nosauktās vērtības vērtības tiek uzskatītas par vērtībām, bet nenosauktās atsauces uz objektiem tiek uzskatītas par x vērtībām. rvalue atsauces uz funkcijām tiek uzskatītas par lvalues ​​neatkarīgi no tā, vai tās ir nosauktas." (Redzēsimies vēlāk).

Tātad, xvalue ir lvalue vai prvalue, kura resursus (krātuvi) var atkārtoti izmantot. xvalues ​​ir lvalues ​​un prvalues ​​krustojuma kopa.

Xvalue ir vairāk nekā tas, kas ir apskatīts šajā rakstā. Tomēr xvalue ir pelnījis veselu rakstu pats par sevi, un tāpēc šajā rakstā xvalue papildu specifikācijas nav apskatītas.

Izteiksmes kategorijas taksonomijas komplekts

Vēl viens citāts no C ++ specifikācijas:

Piezīme: Vēsturiski vērtības un vērtības bija tā saucamās, jo tās varēja parādīties uzdevuma kreisajā un labajā pusē (lai gan tas parasti vairs nav taisnība); glvalues ​​ir “vispārinātas” vērtības, prvalues ​​ir “tīras” un xvalues ​​ir “eXpiring” vērtības. Neskatoties uz nosaukumiem, šie termini klasificē izteicienus, nevis vērtības. - beigu piezīme ”

Tātad, glvalues ​​ir lvalues ​​un xvalues ​​savienojuma kopa, un rvalues ​​ir xvalues ​​un prvalues ​​savienojuma kopa. xvalues ​​ir lvalues ​​un prvalues ​​krustojuma kopa.

Sākotnēji izteicienu kategorijas taksonomija ir labāk ilustrēta ar Venna diagrammu šādi:

Secinājums

Lvalue ir izteiksme, kuras novērtējums nosaka objekta, bitu lauka vai funkcijas identitāti.

Prvalue ir izteiksme, kuras novērtējums inicializē objektu vai bitu lauku vai aprēķina operatora operanda vērtību, kā norādīts kontekstā, kurā tā parādās.

Xvalue ir lvalue vai prvalue ar papildu rekvizītu, kuru tā resursus (krātuvi) var atkārtoti izmantot.

C ++ specifikācija ilustrē izteiksmes kategorijas taksonomiju ar koku diagrammu, norādot, ka taksonomijā ir zināma hierarhija. Līdz šim taksonomijā nav hierarhijas, tāpēc daži autori izmanto Venna diagrammu, jo tā taksonomiju ilustrē labāk nekā koku diagramma.

AppyMouse ekrāna skārienpaliktnis un peles rādītājs Windows planšetdatoriem
Planšetdatoru lietotājiem bieži pietrūkst peles rādītāja, it īpaši, ja viņi parasti lieto klēpjdatorus. Skārienekrāna viedtālruņiem un planšetdatoriem...
Vidējā peles poga nedarbojas sistēmā Windows 10
The peles vidējā poga palīdz jums ritināt garas tīmekļa lapas un ekrānus ar lielu datu daudzumu. Ja tas apstājas, jūs galu galā izmantosiet tastatūru,...
Kā nomainīt peles kreiso un labo pogu operētājsistēmā Windows 10
Tas ir diezgan normāli, ka visas datora peles ierīces ir ergonomiski izstrādātas lietotājiem ar labo roku. Bet ir pieejamas peles ierīces, kas ir īpaš...