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.

ad-banner

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!

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<int, int >>>?

Cateva caracteristici minunate C moderne pe care fiecare dezvoltator

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!

1611681067 332 Cateva caracteristici minunate C moderne pe care fiecare dezvoltator

Î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?

Cateva caracteristici minunate C moderne pe care fiecare dezvoltator
smh?

De fapt, a fost introdus C ++ 11 std::initializer_list<type>. Lista inițializată cu paranteze va fi considerată ca acest container ușor dacă declared 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:

1611681067 804 Cateva caracteristici minunate C moderne pe care fiecare dezvoltator

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.

1611681068 837 Cateva caracteristici minunate C moderne pe care fiecare dezvoltator

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ă obiecte a 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:

1611681068 486 Cateva caracteristici minunate C moderne pe care fiecare dezvoltator

Î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.

1611681068 218 Cateva caracteristici minunate C moderne pe care fiecare dezvoltator
Se simt veseli după ce au aflat despre C ++ modern! (Fotografie de Ian Schneider pe Unsplash)

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.

1611681068 689 Cateva caracteristici minunate C moderne pe care fiecare dezvoltator

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.

1611681069 727 Cateva caracteristici minunate C moderne pe care fiecare dezvoltator

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.

1611681069 638 Cateva caracteristici minunate C moderne pe care fiecare dezvoltator

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!