Ca limbaj, C ++ a evoluat foarte mult.
Desigur, acest lucru nu s-a întâmplat peste noapte. A fost o perioadă în care C ++ nu avea dinamism. Era greu să-ți placă limba.
Dar lucrurile s-au schimbat când comitetul standard C ++ a decis să învârtă volanul.
Din 2011, C ++ a apărut ca un limbaj dinamic și în continuă evoluție, pe care mulți oameni l-au sperat.
Nu vă înțelegeți greșit că limba a devenit mai ușoară. Este încă unul dintre cele mai dificile limbaje de programare, dacă nu chiar cel mai greu, care sunt utilizate pe scară largă. Dar C ++ a devenit, de asemenea, mult mai ușor de utilizat decât versiunile sale anterioare.
În ultima mea postare, am vorbit despre Bibliotecă de algoritmi C ++ care s-a îmbogățit în ultimii doi ani.
Astăzi, vom analiza câteva funcții noi (începând de la C ++ 11, care are deja 8 ani apropo) pe care fiecare dezvoltator ar dori să le cunoască.
De asemenea, rețineți că am omis câteva caracteristici avansate din acest articol, dar sunt dispus să scriu despre ele în viitor. ? ️
Merge!
Conţinut
Cuvântul cheie automat
Când a fost introdus pentru prima dată C ++ 11 auto
, viața a devenit mai ușoară.
Ideea de auto
a fost de a face compilatorul C ++ să deducă tipul datelor dvs. în timp ce compilați – în loc să vă declarați tipul de fiecare dată-ciudat. A fost atât de convenabil atunci când aveți tipuri de date precum map<string,vector<pair<i
nt, int >>>?
Uită-te la numărul de linie 5. Nu poți declara ceva fără un initializer
. Asta are sens. Linia 5 nu permite compilatorului să știe care poate fi tipul de date.
Inițial, auto
a fost oarecum limitat. Apoi, în versiunile ulterioare ale limbajului, i s-a adăugat mai multă putere!
În rândurile 7 și 8, am folosit inițializarea între paranteze. Aceasta a fost, de asemenea, o nouă caracteristică adăugată în C ++ 11.
Amintiți-vă, în caz de utilizare auto
, trebuie să existe o modalitate în care compilatorul să deducă tipul dvs.
Acum o întrebare foarte frumoasă, ce se întâmplă dacă scriem auto a = {1, 2, 3}
? Este o eroare de compilare? Este un vector?
De fapt, a fost introdus C ++ 11 std::initializer_list<ty
pe>. Lista inițializată cu paranteze va fi considerată ca acest container ușor dacă declare
d auto.
În cele din urmă, așa cum am menționat anterior, deducerea de tip de către compilator poate fi cu adevărat utilă atunci când aveți structuri de date complexe:
Nu uitați să verificați linia 25! Expresia auto [v1,v2] = itr.second
este literalmente o caracteristică nouă în C ++ 17. Aceasta se numește legătură structurată. În versiunile anterioare ale limbii, trebuia să extrageți fiecare variabilă separat. Dar legarea structurată a făcut-o mult mai convenabilă.
Mai mult, dacă doriți să obțineți datele folosind referința, ați adăuga doar un simbol – auto &[v1,v2] = itr.second
.
Ingrijit.
Expresia lambda
C ++ 11 a introdus expresii lambda, ceva de genul funcțiilor anonime în JavaScript. Sunt obiecte funcționale, fără nume și captează variabile pe diverse scopuri bazată pe o sintaxă concisă. De asemenea, acestea pot fi atribuite variabilelor.
Lambdas sunt foarte utile dacă aveți nevoie de ceva rapid rapid în codul dvs., dar nu sunteți dispus să scrieți o funcție complet separată pentru asta. O altă utilizare destul de obișnuită este utilizarea acestora ca funcții de comparare.
Exemplul de mai sus are multe de spus.
În primul rând, observați cât de inițializat cu cretele crește greutatea pentru dvs. Apoi vine generic begin(), end()
acesta este, de asemenea, un adaos în C ++ 11. Apoi vine funcția lambda ca un comparator pentru datele dvs. Se declară parametrii funcției lambda auto
care a fost adăugat în C ++ 14. Înainte de asta, nu am putut folosi auto
pentru parametrii funcției.
Rețineți cum începem expresia lambda cu o paranteză pătrată []
. Acestea definesc domeniul de aplicare al lambda – câtă autoritate are asupra variabilelor și obiectelor locale.
Așa cum este definit în acest document depozit minunat pe C ++ modern:
-
[]
– nu surprinde nimic. Deci, nu puteți utiliza nicio variabilă locală a scopului exterior din interiorul expresiei lambda. Puteți utiliza numai parametrii. -
[=]
– captează obiecte locale (variabile locale, parametri) în domeniu după valoare. Le puteți utiliza, dar nu le puteți modifica. -
[&]
– captează obiecte locale (variabile locale, parametri) în scop prin referință. Le puteți modifica. Ca exemplul următor. -
[this]
– capturăthis
indicatorul după valoare. -
[a, &b]
– captează obiectea
după valoare,b
de referință.
Deci, dacă, în interiorul funcției dvs. lambda, doriți să vă transformați datele într-un alt format, puteți utiliza lambda profitând de scop. De exemplu:
În exemplul de mai sus, dacă ați fi capturat variabile locale după valoare ([factor]
) în expresia ta lambda, nu te-ai putut schimba factor
în linia 5. Pentru că pur și simplu, nu aveți dreptul să faceți asta. Nu vă folosiți greșit de drepturi! ?
În cele din urmă, observați că luăm val
ca referinta. Acest lucru asigură că orice modificare din funcția lambda modifică efectiv vector
.
Declarații inițiale în interiorul if & switch
Mi-a plăcut foarte mult această caracteristică a C ++ 17 imediat după ce am aflat-o.
Deci, aparent, acum puteți face inițializarea variabilelor și puteți verifica starea pe aceasta – simultan în interiorul if/switch
bloc. Acest lucru este foarte util pentru a vă menține codul concis și curat. Forma generală este:
if( init-statement(x); condition(x)) {
// do some stuff here
} else {
// else has the scope of x
// do some other stuff
}
Faceți-o în timp de compilare prin constexpr
constexpr
este rece!
Spuneți că aveți o anumită expresie de evaluat și că valoarea ei nu se va schimba odată inițializată. Puteți pre-calcula valoarea și apoi utilizați-o ca macro. Sau așa cum este oferit C ++ 11, puteți utiliza constexpr
.
Programatorii tind să reducă cât mai mult timpul de rulare al programelor lor. Deci, dacă există unele operații, puteți face compilatorul să efectueze și să scoată încărcarea din timpul de rulare, atunci timpul de rulare poate fi îmbunătățit.
Codul de mai sus este un exemplu foarte comun de constexpr
.
Întrucât am declarat funcția de calcul Fibonacci ca constexpr
, compilatorul poate pre-calcula fib(20)
în timpul compilării. Deci, după compilare, poate înlocui linia
const long long bigval = fib(20);
cu
const long long bigval = 2432902008176640000;
Rețineți că argumentul trecut este un const
valoare. Acesta este un punct important al funcțiilor declarate constexpr
– argumentele transmise ar trebui să fie și ele constexpr
sau const
. În caz contrar, funcția se va comporta ca o funcție normală, ceea ce înseamnă că nu se precalculează în timpul timpului de compilare.
Variabilele pot fi, de asemenea constexpr
, de asemenea. În acest caz, după cum puteți ghici, aceste variabile trebuie să fie evaluate în timp de compilare. În caz contrar, veți primi o eroare de compilare.
Interesant, mai târziu în C ++ 17, constexpr-if
și constexpr-lambda
au fost introduse.
Tuples
Mai mult ca pair
, tuple
este o colecție de valori de dimensiuni fixe pentru diferite tipuri de date.
Uneori este mai convenabil de utilizat std::array
in loc de tuple
. array
este similar cu matricea simplă de tip C împreună cu câteva funcționalități ale bibliotecii standard C ++. Această structură de date a fost adăugată în C ++ 11.
Deducerea argumentului șablonului clasei
Un nume foarte detaliat pentru o caracteristică. Ideea este că, din C ++ 17, deducerea argumentelor pentru șabloane se va întâmpla și pentru șabloanele de clasă standard. Anterior, era acceptat doar pentru șabloanele de funcții.
Ca rezultat,
std::pair<std::string, int> user = {"M", 25}; // previous
std::pair user = {"M", 25}; // C++17
Tipul deducției se face implicit. Acest lucru devine și mai convenabil pentru tuple
.
// previous
std::tuple<std::string, std::string, int> user ("M", "Chy", 25);
// deduction in action!
std::tuple user2("M", "Chy", 25);
Această caracteristică de mai sus nu va avea niciun sens dacă nu sunteți familiarizați cu șabloanele C ++.
Indicatoare inteligente
Indicatorii pot fi infernali.
Datorită libertății oferite de limbaje precum C ++ programatorilor, uneori devine foarte ușor să te împuști în picior. Și, în multe cazuri, indicatorii sunt responsabili pentru rău.
Din fericire, C ++ 11 a introdus indicatoare inteligente, indicatoare care sunt mult mai convenabile decât indicatoarele brute. Ajută programatorii să prevină scurgerile de memorie, eliberându-l atunci când este posibil. De asemenea, oferă siguranță excepțională.
M-am gândit să scriu despre indicatoarele inteligente în C ++ în această postare. Dar se pare că există o mulțime de detalii importante despre ele. Ei își merită propria postare și cu siguranță sunt dispus să scriu unul despre ei în viitorul apropiat.
Asta e tot pentru astăzi. Amintiți-vă că C ++ a adăugat de fapt mai multe funcții mai noi în cele mai recente versiuni ale limbajului. Ar trebui să le verificați dacă vă simțiți interesat. Iată un depozit minunat despre C ++ modern, care este numit literalmente Minunat C ++ modern!
Adios!
#Câteva #caracteristici #minunate #moderne #care #fiecare #dezvoltator #trebui #să #cunoască
Câteva caracteristici minunate C ++ moderne pe care fiecare dezvoltator ar trebui să le cunoască