C++

Versiunea actuală a paginii nu a fost încă examinată de colaboratori experimentați și poate diferi semnificativ de versiunea revizuită la 31 iulie 2022; verificările necesită 14 modificări .
C++
Semantică multi- paradigma : orientat pe obiecte , generic , procedural , metaprogramare
Clasa de limba limbaj de programare orientat pe obiecte , limbaj de programare multi -paradigma , limbaj de programare procedural , limbaj de programare functional ,de programare generic , limbaj de programare , limbaj cu forma libera [d] si limbaj de programare compilat
Tipul de execuție compilate
Aparut in 1983
Autor Stroustrup, Bjorn
Extensie de fișier .cc, .cpp, .cxx, .c, .c++, .h, .hpp, .hh, .hxxsau.h++
Eliberare
Tip sistem static
Implementări majore GNU C++ , Microsoft Visual C++ , compilator Intel C++ , compilator Open64 C++ , Clang , Comeau C/C++ , Embarcadero C++ Builder , compilator Watcom C++ , Digital Mars C++, compilator Oracle Solaris Studio C++, Turbo C++
Dialectele ISO/IEC 14882 C++
A fost influențat C , Simula , Algol 68 , Clu , ML și Ada
Site-ul web isocpp.org
 Fișiere media la Wikimedia Commons

C ++ (pronunțat c-plus-plus [2] [3] ) este un limbaj de programare compilat , tip static , de uz general

Suportă paradigme de programare precum programarea procedurală , programarea orientată pe obiecte , programarea generică . Limbajul are o bibliotecă standard bogată care include containere și algoritmi obișnuiți , I/O, expresii regulate, suport pentru multithreading și multe altele. C++ combină caracteristicile atât ale limbajelor de nivel înalt, cât și ale limbajelor de nivel scăzut [4] [5] . În comparație cu predecesorul său - limbajul C  - cea mai mare atenție este acordată suportului pentru programarea orientată pe obiecte și generică [5] .

C++ este utilizat pe scară largă pentru dezvoltarea de software, fiind unul dintre cele mai populare limbaje de programare [opinii 1] [opinii 2] . Domeniul său de aplicare include crearea de sisteme de operare , o varietate de programe de aplicații, drivere de dispozitiv , aplicații pentru sisteme încorporate, servere de înaltă performanță și jocuri pe calculator. Există multe implementări ale limbajului C++, atât gratuite, cât și comerciale, și pentru diverse platforme. De exemplu, pe platforma x86 , acestea sunt GCC , Visual C++ , Intel C++ Compiler , Embarcadero (Borland) C++ Builder și altele. C++ a avut un impact uriaș asupra altor limbaje de programare, în special Java și C# .

Sintaxa C++ este moștenită din limbajul C. Unul dintre principiile de proiectare originale a fost menținerea compatibilității cu C. Cu toate acestea, C++ nu este strict un superset al lui C; Setul de programe care pot fi traduse la fel de bine de către compilatoarele C și C++ este destul de mare, dar nu include toate programele C posibile .

Istorie

Stadiul istoric al dezvoltării [6] An
limbajul BCPL 1966
Limbajul B (dezvoltare originală de Thompson sub UNIX ) 1969
limbajul C 1972
C cu clase 1980
C84 1984
Cfront (ediția E) 1984
cfront (versiunea 1.0) 1985
Moștenire multiplă/virtuală 1988
Programare generică ( şabloane ) 1991
ANSI C++ / ISO-C++ 1996
ISO/IEC 14882:1998 1998
ISO/IEC 14882:2003 2003
C++/CLI 2005
TR1 2005
C++11 2011
C++14 2014
C++17 2017
C++20 2020

Creare

Limbajul a apărut la începutul anilor 1980 , când angajatul Bell Labs , Björn Stroustrup , a venit cu o serie de îmbunătățiri ale limbajului C pentru propriile nevoi [7] . Când Stroustrup a început să lucreze la Bell Labs, la sfârșitul anilor 1970 , cu privire la problemele legate de teoria cozilor de așteptare (așa cum se aplică modelării apelurilor telefonice), a descoperit că încercările de a folosi limbaje de modelare existente la acea vreme erau ineficiente și utilizarea limbajelor de mașină foarte eficiente. ​​a fost prea dificil pentru că pentru expresivitatea lor limitată. De exemplu, limbajul Simula are caracteristici care ar fi foarte utile pentru dezvoltarea de software de mari dimensiuni, dar este prea lent, iar limbajul BCPL este suficient de rapid, dar prea aproape de limbajele de nivel scăzut și nu este potrivit pentru dezvoltarea de software de mari dimensiuni.

Reamintind experiența disertației sale, Stroustrup a decis să completeze limbajul C (succesorul BCPL) cu capabilitățile disponibile în limbajul Simula. Limbajul C, fiind limbajul de bază al sistemului UNIX pe care rulau computerele Bell, este rapid, bogat în funcții și portabil. Stroustrup i-a adăugat capacitatea de a lucra cu clase și obiecte. Ca urmare, problemele practice de modelare s-au dovedit a fi accesibile atât în ​​ceea ce privește timpul de dezvoltare (datorită utilizării claselor de tip Simula), cât și în ceea ce privește timpul de calcul (datorită vitezei lui C). Primele completări la C au fost clasele (cu încapsulare ), moștenirea claselor, verificarea strictă a tipului, funcțiile în linie și argumentele implicite . Versiunile timpurii ale limbii, numite inițial „C cu clase”, au fost disponibile încă din anii 1980 .

În timp ce dezvolta C cu clase , Stroustrup a scris programul cfront  , un compilator care reprocesează codul sursă C cu clase în cod sursă simplu C. Acest lucru ne-a permis să lucrăm la un nou limbaj și să-l folosim în practică, folosind infrastructura deja disponibilă în UNIX pentru dezvoltare în C. Un nou limbaj, neașteptat pentru autor, a câștigat o mare popularitate în rândul colegilor și în curând Stroustrup nu l-a mai putut susține personal, răspunzând la mii de întrebări.

Până în 1983, limbii au fost adăugate noi caracteristici, cum ar fi funcții virtuale, supraîncărcare de funcții și operatori, referințe, constante, controlul utilizatorului asupra gestionării memoriei libere, verificare îmbunătățită a tipului și un nou stil de comentariu ( //). Limbajul rezultat nu mai este doar o versiune augmentată a clasicului C și a fost redenumit din C cu clase în „C++”. Prima sa lansare comercială a avut loc în octombrie 1985 .

Înainte de începerea standardizării oficiale, limbajul a fost dezvoltat în principal de Stroustrup, ca răspuns la solicitările din partea comunității de programare. Funcția descrierilor în limbaj standard a fost îndeplinită de lucrările tipărite ale lui Stroustrup pe C++ (o descriere a limbajului, un manual de referință și așa mai departe). Abia în 1998 a fost ratificat standardul internațional pentru limbajul C++: ISO/IEC 14882:1998 „Standard pentru limbajul de programare C++”; după adoptarea corecțiilor tehnice la standard în 2003,  următoarea versiune a acestui standard este ISO/IEC 14882:2003 [8] .

Dezvoltarea și standardizarea limbii

În 1985, a apărut prima ediție a Limbului de programare C++ , oferind prima descriere a limbajului, care a fost extrem de importantă din cauza lipsei unui standard oficial. În 1989, a fost lansată versiunea C++ 2.0. Noile sale caracteristici includ moștenirea multiplă, clase abstracte, funcții membre statice, funcții constante și membri protejați. În 1990, a fost publicat „Ghidul de referință comentat pentru C++”, care a devenit ulterior baza standardului. Actualizările recente au inclus șabloane, excepții, spații de nume, noi modele și tipul boolean. Biblioteca de șabloane standard (STL) dezvoltată de Alexander Stepanov și Meng Li a fost aleasă ca bază pentru stocarea și accesarea algoritmilor generici .

Biblioteca standard C++ a evoluat și ea odată cu ea. Prima adăugare la biblioteca standard C++ a fost fluxurile I/O, oferind un mijloc de a înlocui C printfși scanf. Mai târziu, cea mai semnificativă dezvoltare a bibliotecii standard a fost includerea Bibliotecii standard de șabloane .

C++ continuă să evolueze pentru a satisface cerințele moderne. Unul dintre grupurile care dezvoltă limbajul C++ și trimit propuneri de îmbunătățire a acestuia către comitetul de standardizare C++ este Boost , care este angajat, printre altele, în îmbunătățirea capacităților limbajului prin adăugarea de caracteristici de metaprogramare la acesta .

Nimeni nu deține drepturile asupra limbajului C++, este gratuit. Cu toate acestea, documentul standard de limbă în sine (cu excepția proiectelor) nu este disponibil gratuit [10] . Ca parte a procesului de standardizare, ISO produce mai multe tipuri de publicații. În special, rapoartele tehnice și specificațiile tehnice sunt publicate atunci când „viitorul este în vedere, dar nu există posibilitatea imediată de acord pentru publicarea unui standard internațional”. Până în 2011, au fost publicate trei rapoarte tehnice despre C++: TR 19768: 2007 (cunoscut și ca Raport tehnic C++ 1) pentru extensiile de bibliotecă integrate în principal în C++11, TR 29124: 2010 pentru funcții matematice speciale și TR 24733: 2011 pentru aritmetică zecimală în virgulă mobilă. Specificație tehnică DTS 18822:. 2014 (prin sistem de fișiere) a fost aprobat la începutul anului 2015, iar restul caietului de sarcini sunt în curs de elaborare și așteaptă aprobare [11] .

În martie 2016, grupul de lucru WG21 C++ a fost creat în Rusia . Grupul a fost organizat pentru a colecta propuneri pentru standardul C++, a le înainta comitetului și a le apăra în cadrul reuniunilor generale ale Organizației Internaționale pentru Standardizare (ISO) [12] .

Istoria numelui

Numele de limbă rezultat provine de la operatorul de increment postfix unar C ++(incrementând valoarea unei variabile cu unu). Numele C+ nu a fost folosit deoarece este o eroare de sintaxă în C și, în plus, numele a fost preluat de un alt limbaj. De asemenea, limbajul nu a fost numit D pentru că „ este o extensie a lui C și nu încearcă să rezolve problemele prin eliminarea elementelor C ” [7] .

Filosofia C++

În The Design and Evolution of C++ [13] , Bjorn Stroustrup descrie principiile pe care le-a urmat atunci când a proiectat C++. Aceste principii explică de ce C++ este așa. Unii dintre ei:

Prezentare generală a limbii

Standardul C++ constă din două părți principale: o descriere a limbajului de bază și o descriere a bibliotecii standard.

La început, limbajul s-a dezvoltat în afara cadrului formal, în mod spontan, în funcție de sarcinile cu care i s-a confruntat. Dezvoltarea limbajului a fost însoțită de dezvoltarea compilatorului cfront cross . Inovațiile în limbaj s-au reflectat în schimbarea numărului de versiune a compilatorului încrucișat. Aceste numere de versiuni cross-compiler s-au extins la limbajul în sine, dar versiunile C++ nu sunt discutate în prezent. Abia în 1998 limba a devenit standardizată.

spațiu de nume Foo { const int x = 5 ; } const int y = Foo :: x ;

Un spațiu de nume fără nume este un caz special. Toate numele descrise în acesta sunt disponibile numai în unitatea de traducere curentă și au legături locale. Spațiul de nume stdconține bibliotecile standard C++.

  • newOperatorii , new[], deleteși sunt introduși să lucreze cu memoria delete[]. Spre deosebire de biblioteca malloc și free care a venit din C, acești operatori inițializează un obiect. Pentru clase, acesta este un apel de constructor, pentru tipurile POD , inițializarea poate fi fie omisă ( new Pod;), fie inițializată cu valori zero ( new Pod(); new Pod {};).

Tipuri

Următoarele tipuri încorporate sunt disponibile în C++. Tipurile C++ sunt aproape identice cu tipurile de date C :

  • caracter: char, wchar_t( char16_tși char32_t, în standardul C++11 );
  • numere întregi cu semn: signed char, short int, int, long int(și long long, în standardul C++11 );
  • numere întregi fără semn: unsigned char, unsigned short int, unsigned int, unsigned long int(și unsigned long long, în standardul C++11 );
  • virgulă mobilă : float, double, long double;
  • boolean: boolavând valorile fie true, fie false.

Operatorii de comparație returnează tipul bool. Expresiile dintre paranteze după if, while sunt convertite la tipul bool[14] .

Limbajul a introdus conceptul de referințe, iar din standardul C++11 , rvalues ​​​​- referințe și referințe de redirecționare .  (vezi Link (C++) )

C++ adaugă caracteristici orientate pe obiecte la C. Introduce clase care oferă cele mai importante trei proprietăți ale POO : încapsulare , moștenire și polimorfism .

În standardul C++, o clasă este un tip definit de utilizator, declarat folosind unul dintre cuvintele cheie sau class, structo unionstructură este o clasă definită de struct, iar uniunea este o clasă definită de union. În funcție de cuvântul cheie utilizat, unele proprietăți ale clasei în sine se modifică. De exemplu, într-o clasă declarată cu struct, membrii fără un modificator de acces atribuit manual vor fi implicit publici și nu privat.

În corpul unei definiții de clasă, puteți specifica atât declarațiile de funcție, cât și definiția lor. În acest din urmă caz, funcția este inline ( inline). Funcțiile membre nestatice pot avea constși calificatori volatile, precum și un calificator de referință ( &sau &&).

Moștenire

C++ acceptă moștenirea multiplă . Clasele de bază (clasele strămoși) sunt specificate în capul declarației de clasă, eventual cu specificatori de acces. Moștenirea din fiecare clasă poate fi publică, protejată sau privată:

Mod de acces/moștenire pentru membrii clasei de bază membru privat membru protejat membru public
moștenire privată nu e disponibil privat privat
protejat-moştenire nu e disponibil protejat protejat
mostenirea publica nu e disponibil protejat public

În mod implicit, clasa de bază este moștenită ca privată.

Ca urmare a moștenirii, clasa copil primește toate câmpurile claselor strămoși și toate metodele acestora; putem spune că fiecare instanță a clasei descendente conține o subinstanță a fiecăreia dintre clasele strămoși. Dacă o clasă strămoșească este moștenită de mai multe ori (acest lucru este posibil dacă este strămoșul mai multor clase de bază ale clasei care este creată), atunci instanțe ale clasei descendente vor include cât mai multe subinstanțe ale acestei clase strămoși. Pentru a evita acest efect dacă nu se dorește, C++ acceptă conceptul de moștenire virtuală . La moștenire, clasa de bază poate fi declarată virtuală; pentru toate aparițiile virtuale ale clasei strămoși în arborele de moștenire al clasei descendente, este creată o singură subinstanță în descendent.

Polimorfism

C++ acceptă polimorfismul dinamic și polimorfismul parametric .

Polimorfismul parametric este reprezentat de:

  • Argumente implicite pentru funcții. De exemplu, pentru o funcție , void f(int x, int y=5, int z=10)apelurile la și sunt echivalente.f(1)f(1,5)f(1,5,10)
  • Supraîncărcarea funcției : O funcție cu același nume poate avea un număr și un tip diferit de argumente. De exemplu :voidPrint ( int x ) ; voidPrint ( dublu x ) ; void Print ( int x , int y );
Supraîncărcarea operatorului este un caz special de supraîncărcare a funcțiilor .
  • motor de șablon

Polimorfismul dinamic este implementat folosind metode virtuale și o ierarhie de moștenire. În C++, un tip este polimorf dacă are cel puțin o metodă virtuală. Exemplu de ierarhie:

Figura de clasă { public : gol virtual Draw () = 0 ; // metoda virtuală pură virtuală ~ Figura ( ); // dacă există cel puțin o metodă virtuală, destructorul trebuie făcut virtual }; Class Square : figură publică { public : void Draw () suprascrie ; }; clasa Cercul : figură publică { public : void Draw () suprascrie ; };

Aici clasa Figure este abstractă (și chiar clasa interfață ), deoarece metoda Draw nu este definită. Obiectele acestei clase nu pot fi create, dar pot fi folosite referințe sau pointeri cu tipul Figure. Alegerea implementării metodei Draw se va face în timpul rulării pe baza tipului real al obiectului.

Încapsulare

Încapsularea în C++ este implementată prin specificarea nivelului de acces la membrii clasei: aceștia sunt publici (publici, public), protejați ( protected) și privați (privati, private). În C++, structurile diferă formal de clase doar prin aceea că implicit nivelul de acces la membrii clasei și tipul de moștenire pentru o structură sunt publice, în timp ce pentru o clasă sunt private.

Acces privat protejat public
Clasa în sine da da da
Prieteni da da da
moștenitori Nu da da
Din afara Nu Nu da

Verificarea accesului are loc în timpul compilării, încercarea de a accesa un membru al clasei inaccesibil va cauza o eroare de compilare.

Prieteni

Funcțiile prieten  sunt funcții care nu sunt funcții membre și totuși au acces la membrii protejați și privați ai clasei. Ele trebuie să fie declarate în corpul clasei ca friend. De exemplu:

class Matrix { prieten Matrix Multiply ( Matrix m1 , Matrix m2 ); };

Aici, funcția Multiplypoate accesa orice câmpuri și funcții membre ale Matrix.

Atât întreaga clasă, cât și o funcție membră a clasei pot fi declarate prietene. Patru restricții importante privind relațiile de prieteni în C++ sunt:

  • Prietenia nu este tranzitivă. Dacă A declară un prieten al lui B, iar B, la rândul său, declară un prieten al lui C, atunci C nu devine automat un prieten al lui A. Pentru a face acest lucru, A trebuie să-l declare în mod explicit pe C prieten.
  • Prietenia nu este reciprocă. Dacă clasa A declară un prieten al clasei B, atunci nu devine automat un prieten al lui B. Pentru aceasta, trebuie să existe o declarație explicită de prietenie a lui A în clasa B.
  • Prietenia nu se moștenește. Dacă A declară o clasă B ca prietenă, atunci copiii lui B nu devin automat prietenii lui A. Pentru a face acest lucru, fiecare dintre ei trebuie să fie declarat în mod explicit prieten al lui A.
  • Prietenia nu se extinde asupra descendenților. Dacă o clasă A îl declară prieten pe B, atunci B nu devine automat un prieten al claselor descendențe ale lui A. Fiecare descendent, dacă este necesar, trebuie să-și declare B propriul prieten.

În general, această regulă poate fi formulată astfel: „Relația de prietenie există doar între acele clase (clasa și funcție) pentru care este declarată explicit în cod, și acționează numai în direcția în care este declarată”.

Caracteristici speciale

O clasă implicită poate avea șase funcții speciale: constructor implicit, constructor de copiere, constructor de mutare, destructor, operator de atribuire de copiere, operator de atribuire de mutare. De asemenea, este posibil să le definiți în mod explicit pe toate (vezi regula celor trei ).

class Array { public : Matrice ( ) = implicit // compilatorul va crea un constructor implicit al Array în sine ( size_t _len ) : len ( _len ) { val = new double [ _len ]; } Array ( const Array & a ) = delete ; // constructorul de copiere a eliminat explicit Array ( Array && a ); // mută constructorul ~ Array () { şterge [] val ; } Array & operator = ( const Array & rhs ); // copiere operator de atribuire Array & operator = ( Array && rhs ); // mutați operatorul de atribuire dublu și operatorul []( size_t i ) { return val [ i ]; } const double & operator []( size_t i ) const { return val [ i ]; } protejat : std :: size_t len ​​​​= 0 ; // inițializare câmp double * val { nullptr }; };

Constructorul este chemat pentru a inițializa obiectul (de tipul corespunzător) atunci când este creat, iar destructorul este chemat pentru a distruge obiectul. O clasă poate avea mai mulți constructori, dar un destructor poate avea doar unul. Constructorii din C++ nu pot fi declarați virtuali, dar destructorii pot, și sunt de obicei declarați pentru toate tipurile polimorfe, pentru a se asigura că un obiect referit sau accesibil prin pointer este distrus corespunzător, indiferent de tipul referinței sau pointerului. Dacă cel puțin una dintre clasele de bază are un destructor virtual, destructorul clasei copil devine automat virtual.

Șabloane

Șabloanele vă permit să generați funcții și clase care sunt parametrizate cu un anumit tip sau valoare. De exemplu, clasa anterioară ar putea implementa o matrice pentru orice tip de date:

template < typenameT > _ class Array { ... T & operator []( size_t i ) { return val [ i ]; } protejat : std :: size_t len ​​​​{ 0 }; // inițializare câmp T * val { nullptr }; };

Bibliotecă standard

Structura generală

Biblioteca standard C++ include un set de instrumente care ar trebui să fie disponibile pentru orice implementare a limbajului pentru a oferi programatorilor o utilizare confortabilă a caracteristicilor limbajului și pentru a oferi o bază pentru dezvoltarea atât a unei game largi de aplicații, cât și a bibliotecilor specializate. Biblioteca standard C++ include o parte din biblioteca standard C. Standardul C++ conține o referință normativă la standardul C din 1990 și nu definește în mod independent acele funcții standard ale bibliotecii care sunt împrumutate din biblioteca standard C.

#includeAccesul la capabilitățile bibliotecii standard C++ este asigurat prin includerea fișierelor de antet standard adecvate în program (prin directiva ). În total, 79 de astfel de fișiere sunt definite în standardul C++11. Facilitățile standard de bibliotecă sunt declarate ca parte a spațiului de nume std. Fișierele antet ale căror nume se potrivesc cu modelul „cX”, unde X este numele fișierului antet al Bibliotecii standard C fără extensie (cstdlib, cstring, cstdio etc.), conțin declarații corespunzătoare acelei părți a bibliotecii standard C. funcțiile standard ale bibliotecii se găsesc și în namespace std.

Compoziție

Biblioteca standard include următoarele secțiuni:

  • Suport lingvistic . Include instrumente care sunt necesare pentru ca programele să funcționeze, precum și informații despre caracteristicile de implementare. Alocarea memoriei, RTTI , excepții de bază, limite de valoare pentru tipurile de date numerice, interacțiuni de bază cu mediul, cum ar fi ceasul sistemului, gestionarea semnalului UNIX, terminarea programului.
  • containere standard . Biblioteca standard include șabloane pentru următoarele containere: matrice dinamică (vector), matrice statică (matrice), liste unidirecționale și bidirecționale (listă_înainte, listă), stivă (stivă), deque (deque), matrice asociative (hartă, multimap), seturi (set, multiset), coada de prioritate (priority_queue).
  • Utilități de bază . Această secțiune include o descriere a principalelor elemente de bază utilizate în biblioteca standard, alocatoare de memorie și suport pentru oră și dată în stil C.
  • Iteratori . Furnizați șabloane iteratoare care oferă un mecanism standard în biblioteca standard pentru a aplica algoritmi de procesare a datelor în loturi elementelor containerului.
  • Algoritmi . Șabloane pentru descrierea operațiilor de prelucrare care, folosind mecanismele bibliotecii standard, pot fi aplicate oricărei secvențe de elemente, inclusiv elementelor din containere. De asemenea, în această secțiune sunt incluse descrieri ale funcțiilor bsearch() și qsort() din biblioteca standard C.
  • Coarde . Șabloane de șir în stil C++. Această secțiune include și câteva dintre bibliotecile pentru lucrul cu șiruri și simboluri în stil C.
  • Intrare-ieșire . Șabloane și clase de ajutor pentru fluxuri I/O generale, I/O șir, manipulatoare (controale de format de I/O în stil C++).
  • Localizare . Definiții utilizate pentru a sprijini naționalitățile și formatele de prezentare în stil C++ și în stil C (date, valute etc.).
  • Diagnosticare . Definiții ale unui număr de excepții și mecanisme de verificare a aserțiunilor în timpul execuției (assert). Suport pentru tratarea erorilor în stil C.
  • Numerele . Definiții pentru lucrul cu numere complexe, vectori matematici, suport pentru funcții matematice generale, generator de numere aleatorii.

Containerele, șirurile de caractere, algoritmii, iteratoarele și utilitățile de bază, cu excepția împrumuturilor din biblioteca C, sunt numite colectiv STL (Standard Template Library - bibliotecă standard de șabloane). Inițial, această bibliotecă a fost un produs separat și abrevierea sa a fost descifrată diferit, dar apoi a intrat în biblioteca standard C++ ca element integral. Denumirea reflectă faptul că mecanismele de programare generalizate (șabloane C++ - șablon) sunt folosite pentru a implementa instrumente de uz general (containere, șiruri de caractere, algoritmi). Scrierile lui Stroustrup detaliază motivele pentru care s-a făcut această alegere. Principalele sunt universalitatea mai mare a soluției alese (containerele șablon, spre deosebire de containerele de obiecte, pot fi utilizate cu ușurință pentru tipurile non-obiecte și nu necesită un strămoș comun pentru tipurile de elemente) și eficiența sa tehnică (de regulă, container șablon operațiunile nu necesită apeluri de funcții virtuale și pot fi ușor încorporate (inline), ceea ce oferă în cele din urmă un câștig de performanță).

Începând cu standardul C++11, au fost adăugate următoarele caracteristici:

  • A fost adăugată biblioteca <regex>, care implementează mecanisme comune de căutare și înlocuire folosind expresii regulate.
  • S-a adăugat suport pentru multithreading.
  • Operații atomice
  • variante neordonate de tablouri si multimi asociative.
  • Indicatori inteligente care dealoca automat memoria alocată.

Implementări

STL, înainte de a fi inclus în standardul C++, a fost o dezvoltare terță parte, mai întâi de către HP și apoi de către SGI . Standardul de limbă nu îl numește „STL”, deoarece această bibliotecă a devenit parte integrantă a limbii, totuși mulți oameni încă folosesc acest nume pentru a o deosebi de restul bibliotecii standard (fluxuri I/O ( iostream ), subsecțiunea C si altele).

Un proiect numit STLport [15] bazat pe SGI STL menține la zi clasele STL, IOstream și string. Câteva alte proiecte dezvoltă, de asemenea, utilizări private ale bibliotecii standard.

Diferențele față de limbajul C

Compatibilitate cu limbajul C

Alegerea lui C ca bază pentru crearea unui nou limbaj de programare se explică prin faptul că limbajul C:

  1. este un limbaj polivalent, concis și de nivel relativ scăzut;
  2. potrivit pentru majoritatea sarcinilor de sistem;
  3. executat peste tot și pe orice;
  4. interfețe cu mediul de programare UNIX.
— B. Stroustrup. limbaj de programare C++. Secțiunea 1.6 [16]

În ciuda unui număr de deficiențe binecunoscute ale limbajului C, Stroustrup a ales să-l folosească ca bază pentru că „C are problemele sale, dar un limbaj conceput de la zero le-ar avea, iar noi cunoaștem problemele lui C”. În plus, acest lucru ne-a permis să obținem rapid un prototip de compilator ( cfront ) care a tradus doar elementele de sintaxă adăugate în limbajul C original.

Pe măsură ce C++ s-a dezvoltat, au fost incluse și alte caracteristici care suprascriu capacitățile constructelor C și problema renunțării la compatibilitatea limbajului prin eliminarea constructelor depreciate a fost ridicată în mod repetat. Cu toate acestea, compatibilitatea a fost menținută din următoarele motive:

  • păstrarea codului actual, scris inițial în C și portat direct în C++;
  • eliminarea nevoii de recalificare a programatorilor care au studiat anterior C (au nevoie doar să învețe noi instrumente C++);
  • eliminarea confuziei între limbi atunci când acestea sunt folosite împreună („dacă două limbi sunt folosite împreună, diferențele lor ar trebui să fie fie minime, fie atât de mari încât limbile să nu poată fi confundate”).

Caracteristici noi

Noile caracteristici C++ includ declarații de expresie, conversii ale tipului de funcție, operatori newși delete, tip bool, referințe, constanță extinsă, funcții inline, argumente implicite, suprascrieri, spații de nume, clase (inclusiv toate caracteristicile legate de clasă, cum ar fi moștenirea, funcțiile membre, funcțiile virtuale, abstractele). clase și constructori ), înlocuiri de operator, șabloane, operator ::, gestionarea excepțiilor, identificare dinamică și multe altele. Limbajul C++ este, de asemenea, în multe cazuri, mai strict în ceea ce privește verificarea tipului decât C.

C++ a introdus comentarii cu două bare oblice ( //) care erau în predecesorul lui C, BCPL .

constUnele caracteristici ale C++ au fost ulterior portate în C, cum ar fi cuvintele cheie și , inlinedeclarațiile de buclă forși comentariile în stil C++ ( //). Implementările ulterioare ale C au introdus și caracteristici care nu se găsesc în C++, cum ar fi macrocomenzi va_argși gestionarea îmbunătățită a parametrilor matricei.

C++ nu include C

În timp ce majoritatea codului C va fi valabil și pentru C++, C++ nu este un superset al C și nu îl include. Există, de asemenea, un cod care este adevărat pentru C, dar nu pentru C++. Acest lucru îl deosebește de Obiectivul C , o altă îmbunătățire C pentru OOP , care este doar un superset de C.

Există și alte diferențe. De exemplu, C++ nu permite apelarea unei funcții main()în interiorul unui program, în timp ce în C este legală. De asemenea, C++ este mai strict în unele privințe; de exemplu, nu permite turnarea implicită între tipuri de pointer nelegate și nu permite funcții care nu sunt încă declarate.

Mai mult, codul care este valabil pentru ambele limbi poate produce rezultate diferite în funcție de compilatorul în care limbă este tradus. De exemplu, pe majoritatea platformelor, următorul program afișează „C” dacă este compilat de un compilator C și „C++” dacă este compilat de un compilator C++. Acest lucru se datorează faptului că constantele de caractere în C (de exemplu, 'a') sunt de tip int, dar în C++ sunt de tip char, iar dimensiunile acestor tipuri de obicei diferă.

#include <stdio.h> int main () { printf ( "%s \n " , ( dimensiunea ( 'a ' ) == dimensiunea ( caracter )) ? "C++" : "C" ); returnează 0 ; }

C Mijloace de evitat

După cum notează Stroustrup, „Cu cât cunoașteți mai bine C, cu atât vă va fi mai dificil să evitați programarea C++ în stilul C, pierzând în același timp beneficiile potențiale ale C++”. În acest scop, el face următorul set de recomandări pentru programatorii C pentru a profita din plin de C++:

  • Nu utilizați macrocomenzi #define. Pentru a declara constante, utilizați const, grupuri de constante (enumerări) - enum, pentru includerea directă a funcțiilor - inline, pentru a defini familii de funcții sau tipuri - template.
  • Nu utilizați declarații de variabile forward. Declarați variabilele în blocul în care sunt utilizate efectiv, combinând întotdeauna declararea cu inițializarea.
  • Renunțați la utilizarea lui malloc()[17] în favoarea operatorului new, din realloc()[18]  în favoarea tipului vector. Va fi mai sigur să folosiți indicatoare inteligente, cum ar fi shared_ptrși unique_ptr, disponibile din a unsprezecea versiune a standardului.
  • Evitați pointerii netipați, aritmetica pointerului, turnările implicite, uniunile, cu excepția eventualelor coduri de nivel scăzut. Utilizați conversii de tip „nou”, deoarece exprimă mai precis intențiile reale ale programatorului și sunt mai sigure.
  • Minimizați utilizarea matricelor și șirurilor de caractere în stil C prin înlocuirea lor cu stringși vectorde la tipuri STL. În general, nu încercați să vă creați propriile implementări ale ceea ce este deja în biblioteca standard.

Dezvoltare ulterioară

Actualul standard lingvistic ISO/IEC 14882:2017 a fost publicat în decembrie 2017 . Este denumit în mod neoficial C++17 . Următoarea versiune a standardului, programată pentru 2020, are denumirea neoficială C++20 .

Direcții generale de dezvoltare C++

Potrivit autorului limbii, Björn Stroustrup [19] [20] [21] , vorbind despre dezvoltarea ulterioară și perspectivele limbii, se pot distinge următoarele:

  • Practic, dezvoltarea ulterioară a limbajului va urma calea adăugărilor la biblioteca standard. Una dintre sursele principale pentru aceste suplimente este celebra bibliotecă Boost .
  • Modificările aduse nucleului limbajului nu ar trebui să reducă eficiența C++ care a fost deja atinsă. Din punctul de vedere al lui Stroustrup, este de preferat să se facă câteva schimbări majore majore la bază decât multe modificări mici.
  • Direcțiile de bază pentru dezvoltarea C++ în viitorul apropiat sunt extinderea capacităților și rafinarea instrumentelor de programare generice, standardizarea mecanismelor de procesare paralelă, precum și perfecționarea instrumentelor de programare sigure, cum ar fi diverse verificări și siguranțe. conversii de tip, verificarea stării și așa mai departe.
  • În general, C++ este conceput și dezvoltat ca un limbaj multi-paradigmă care absoarbe diverse metode și tehnologii de programare, dar le implementează pe o platformă care oferă o eficiență tehnică ridicată. Prin urmare, în viitor, este posibil ca limbajului să fie adăugate instrumente de programare funcționale, colectarea automată a gunoiului și alte mecanisme care lipsesc în prezent în limbaj. Dar, în orice caz, acest lucru se va face pe platforma existentă a unui limbaj compilat extrem de eficient.
  • Deși formal unul dintre principiile C++ rămâne acela de a menține compatibilitatea cu limbajul C, de fapt, grupurile de standardizare ale acestor limbi nu interacționează, iar modificările pe care le fac nu numai că nu se corelează, dar adesea contrazic fundamental. reciproc ideologic. Deci, elementele pe care noile standarde C le adaugă la nucleu sunt elemente ale bibliotecii standard din standardul C++ și sunt în general absente în nucleu, de exemplu, matrice dinamice, matrice cu granițe fixe, facilități de procesare paralelă. Stroustrup consideră că combinarea dezvoltării acestor două limbi ar fi de mare beneficiu, dar nu este posibil din motive politice. Deci compatibilitatea practică între C și C++ se va pierde treptat.

Standardul C++11: completări la nucleul limbajului

  • Funcții și expresii constante definite explicit constexpr.
  • Inițializare generică.
  • Constructori și operatori de atribuire cu semantică de transfer.
  • Inferență de tip.
Pentru utilizarea în șabloane, unde este dificil de specificat un anumit tip de variabilă, au fost introduse două mecanisme noi: variabilele de tip autoși declarația decltype.
  • Parcurgeți colecția.
Urmând multe limbaje moderne, C++ a introdus construcția „buclă prin colecție” a formularului for (type &x: array) {...}. Aici, corpul buclei este executat pentru fiecare element al colecției array, iar xîn fiecare iterație se va referi la următorul element al colecției. Colecția poate fi o matrice C sau orice container de bibliotecă standard care definește iteratorii beginși end.
  • Expresii lambda.
S-a adăugat capacitatea de a declara expresii lambda (funcții fără nume definite la punctul de aplicare), inclusiv cele care depind de variabile externe (închideri). Expresiile Lambda pot fi atribuite variabilelor și utilizate oriunde este necesară o funcție de tipul corespunzător, cum ar fi în algoritmii standard de bibliotecă.
  • Modificări în descrierea metodelor virtuale.
A fost adăugat un modificator opțional override, care este utilizat în declararea unei metode care înlocuiește metoda virtuală a clasei părinte. Descrierea substituției cu overrideprovoacă o verificare a prezenței metodei care este înlocuită în clasa părinte și a unei potriviri în semnăturile metodei. A fost adăugat și un modificator final, ca în Java, care interzice înlocuirea ulterioară a metodei marcate cu acesta. De finalasemenea, poate fi declarată o clasă - în acest caz, este interzisă moștenirea de noi clase de la ea. Un cuvânt cheie este definit pentru o constantă - un indicator nul: nullptr. Au fost aduse modificări semanticii și, parțial, sintaxei enumerațiilor și uniunilor. A fost adăugată capacitatea de a crea enumerări sigure, o serie de restricții de structură au fost eliminate din uniuni. Compilatorul trebuie să analizeze corect textul programului cu mai multe paranteze unghiulare de închidere la rând (anterior, secvența „ >>” a fost percepută fără ambiguitate ca o operație de deplasare la dreapta pe biți, prin urmare, în notarea construcțiilor șablon imbricate, era necesar. pentru a separa semnele „mai mare decât” cu spații sau întreruperi de linie).

Exemple de programe

Exemplul #1

Acesta este un exemplu de program Bună, lume! , care imprimă un mesaj pe consolă utilizând biblioteca standard și iese.

#include <iostream> folosind namespace std ; int main () { cout << "Bună, lume!" << endl ; returnează 0 ; }

Exemplul #2

C++ modern vă permite să rezolvați probleme mai complexe într-un mod simplu. Acest exemplu demonstrează, printre altele, utilizarea containerelor Standard Template Library ( STL ).

#include <iostream> // pentru a folosi std::cout #include <vector> // conține o matrice dinamică #include <map> // conține tipul de date din dicționar #include <șir> int main () { // Importă toate declarațiile din spațiul de nume „std” în spațiul de nume global. folosind namespace std ; // Declaram un container asociativ cu chei sir si date ca vectori sir. map < șir , vector < șir > > elemente ; // Adăugați câteva persoane în acest container asociativ și dați-le câteva articole. articole [ „Anya” ]. push_back ( "esarfa" ); articole [ „Dmitry” ]. push_back ( "bilete" ); articole [ „Anya” ]. push_back ( "catel" ); // Buclă prin toate obiectele din container pentru ( const auto & person : items ) { // persoană este o pereche de două obiecte: person.first este numele său, // person.second este o listă a elementelor sale (vector de șiruri) cout << person . primul << " poartă " << persoană . al doilea . dimensiune () << "articole" << endl ; } }

Acest exemplu importă toate numele din spațiul de nume standard pentru simplitate. Într-un program real, acest lucru nu este recomandat, deoarece puteți întâlni coliziuni de nume. Limbajul vă permite să importați obiecte individuale:

#include <vector> int main () { folosind std :: vector ; vector < int > vectorul_meu ; }

În C++ (ca și în C), dacă execuția programului ajunge la sfârșitul funcției main(), atunci aceasta este echivalentă cu return 0;. Acest lucru nu este valabil pentru nicio altă funcție decât main().

Comparație cu limbi alternative

Sunt cunoscute mai multe studii în care s-a încercat compararea mai mult sau mai puțin obiectivă a mai multor limbaje de programare, dintre care unul este C++. În special:

  • În articolul științific „Haskell vs. Ada vs. C++ vs. Awk vs. …” Paul Hudak și Mark Jones [22] raportează despre studiul unui număr de limbaje imperative și funcționale cu privire la soluția unei probleme model de prototipare rapidă a unui sistem GIS militar.
  • În articolul științific „Implementarea DSL în metaocaml, șablon haskell și C++” de patru autori [23] , un studiu metodic al utilizării C++ și a două limbaje funcționale ca instrumente de bază pentru programarea orientată pe limbaj folosind metoda de programare generativă. se realizează .
  • Lutz Prehelt [24] a luat în considerare șapte limbi (C, C++, Java, Perl, Python, Rexx și Tcl) în sarcina de a scrie un program simplu pentru a converti numerele de telefon în cuvinte conform anumitor reguli.
  • În articolul lui David Wheler „Ada, C, C++ și Java vs. Steelman [25] compară limbile Ada, C++, C, Java cu documentul „ Steelman ” - o listă de cerințe de limbă pentru dezvoltarea militară a sistemelor încorporate, care a fost dezvoltată de Comitetul de limbă la nivel înalt al Departamentul Apărării al SUA în 1978. Deși acest document este foarte depășit și nu ține cont de multe dintre proprietățile esențiale ale limbilor moderne, comparația arată că C++, în ceea ce privește setul de caracteristici cerute în industrie, nu este atât de diferit de limbile care pot fi considerați adevărații săi concurenți.
  • Un articol al lui Matthew Forment și Michael Gillings [26] descrie un studiu [27] al implementării în șase limbi — C++, C, C#, Java, Perl, Python — a trei algoritmi specifici utilizați în bioinformatică: metoda vecinului cel mai apropiat , globală alinierea secvenței ( Needleman Algorithm - Wunsha ) și analizarea rezultatelor BLAST .

C++ și Ada

Limbajul Ada este aproape de C++ în ceea ce privește setul său de caracteristici și domenii de aplicare: este un limbaj structural compilat cu o adăugare orientată pe obiect asemănătoare Simula (același model „Algol cu ​​clase” ca și în C++), tastare statică , instrumente de programare generice, concepute pentru dezvoltarea de sisteme software mari și complexe. În același timp, este fundamental diferită în ideologie: spre deosebire de C ++, Ada a fost construită pe baza unor condiții elaborate anterior cu atenție de la producători de software complex, cu cerințe sporite de fiabilitate, care au lăsat o amprentă asupra sintaxei și semanticii limba.

Există puține comparații directe ale eficienței codării Ada și C++. În articolul [22] menționat mai sus, rezolvarea problemei modelului în Ada a rezultat într-un cod cu aproximativ 30% mai mic ca dimensiune (în linii) decât în ​​C++. Comparația proprietăților limbilor înseși este dată în multe surse, de exemplu, articolul lui Jim Rogers despre AdaHome [28] enumeră mai mult de 50 de puncte de diferențe între proprietățile acestor limbi, majoritatea fiind în favoarea lui Ada. (mai multe caracteristici, comportament mai flexibil, șanse mai mici de erori). Deși multe dintre declarațiile susținătorilor Ada sunt controversate, iar unele dintre ele sunt vădit depășite, în general se poate concluziona:

  • Sintaxa Ada este mult mai strictă decât C++. Limbajul necesită aderarea la disciplina de programare, nu încurajează „trucuri de programare”, încurajează scrierea unui cod simplu, logic și ușor de înțeles, ușor de întreținut.
  • Spre deosebire de C++, Ada este extrem de sigură. Un sistem dezvoltat de tipuri permite, sub rezerva disciplinei declararii si utilizarii lor, sa controleze static corectitudinea utilizarii datelor cat mai complet posibil si protejeaza impotriva erorilor accidentale. Conversiile automate de tip sunt reduse la minimum.
  • Pointerii din Ada sunt mult mai strâns controlați decât în ​​C++, iar aritmetica adreselor este disponibilă doar printr-o bibliotecă de sistem separată.
  • Modulele personalizate Ada sunt similare ca funcționalitate cu șabloanele C++, dar oferă un control mai bun.
  • Ada are modularitate încorporată și un sistem de compilare separat standardizat, în timp ce C++ folosește includerea fișierelor text și controalele de compilare și compilare externă.
  • Multitasking-ul încorporat al Ada include sarcini paralele și mecanismul lor de comunicare (intrari, întâlnire, operator select). În C++, toate acestea sunt implementate doar la nivel de bibliotecă.
  • Ada este strict standardizată, datorită căruia oferă o portabilitate mai bună.

Într-un articol al lui Stephen Zeiger de la Rational Software Corporation [29] , se susține că dezvoltarea în Ada este în general cu 60% mai ieftină și are ca rezultat codul cu de 9 ori mai puține defecte decât în ​​C. Deși aceste rezultate nu pot fi transferate direct în C++, ele sunt încă interesante, având în vedere că multe dintre deficiențele C++ sunt moștenite din C.

C++ și Java

Java nu poate fi considerat un înlocuitor complet pentru C++, este conceput ca un limbaj sigur cu un prag de intrare scăzut pentru dezvoltarea aplicațiilor personalizate cu portabilitate ridicată [30] și este fundamental nepotrivit pentru unele tipuri de aplicații care sunt dezvoltate în C++. Cu toate acestea, în domeniul său de aplicare, Java este un concurent foarte real pentru C++. Beneficiile Java sunt frecvent citate ca:

  • Securitate: fără suport pentru indicatorii și aritmetica adreselor, gestionarea automată a memoriei cu colectarea gunoiului, protecție încorporată împotriva erorilor comune ale programelor C++, cum ar fi depășirile de buffer sau depășirile de matrice.
  • Prezența unui sistem dezvoltat de module și compilare separată, mult mai rapid și mai puțin predispus la erori decât preprocesorul și asamblarea manuală a C++.
  • Standardizare și execuție completă într-o mașină virtuală, un mediu dezvoltat, inclusiv biblioteci pentru grafică, interfață cu utilizatorul, acces la baze de date și alte sarcini tipice, ca rezultat - multiplatformă reală.
  • Multithreading încorporat.
  • Subsistemul obiect Java, într-un grad mult mai mare decât C++, se conformează principiului fundamental OOP „ totul este un obiect ”. Interfețele vă permit să oferiți cele mai multe dintre beneficiile moștenirii multiple fără a provoca efectele sale negative.
  • Reflection este mult mai avansat decât în ​​C++ și vă permite să definiți și să schimbați structura obiectelor în timp ce programul rulează.

În același timp, utilizarea colectorului de gunoi și a mașinii virtuale creează limitări greu de depășit. Programele Java tind să fie mai lente, necesită mult mai multă memorie, iar mașina virtuală izolează programul de sistemul de operare, făcând imposibilă programarea la nivel scăzut.

Un studiu empiric [24] nu a găsit nicio diferență semnificativă în viteza de dezvoltare în C++ și Java. Studiul [26] a mai arătat că ideea unei diferențe semnificative în viteza programelor în aceste limbi nu este întotdeauna corectă: în două din trei teste, viteza aplicațiilor în Java și C++ s-a dovedit a fi comparabil. În același timp, Java este mai concis - diferența în cantitatea de cod a fost de aproximativ 10-15%.

C++ și C

C-ul original continuă să evolueze, în el sunt dezvoltate multe proiecte la scară largă: este limbajul principal pentru dezvoltarea sistemelor de operare, motoarele de joc ale multor jocuri dinamice și un număr mare de aplicații sunt scrise în el. O serie de experți susțin că înlocuirea C cu C++ nu crește eficiența dezvoltării, ci duce la complicații inutile ale proiectului, la o fiabilitate redusă și la creșterea costurilor de întreținere. În special:

  • Potrivit lui Linus Torvalds, „C++ provoacă scrierea... o cantitate semnificativă de cod care nu are o importanță fundamentală în ceea ce privește funcționalitatea programului” [opinii 3] .
  • Suportul OOP, șabloanele și STL nu reprezintă un avantaj decisiv al C++, deoarece tot ceea ce sunt folosite este implementat și folosind instrumente C. În același timp, balonarea codului este eliminată, iar unele complicații, care, în plus, sunt departe de a fi necesare, sunt compensate de o mai mare flexibilitate, testare mai ușoară și indicatori de performanță mai buni.
  • Automatizarea accesului la memorie în C++ crește costurile de memorie și încetinește programele.
  • Utilizarea excepțiilor C++ vă obligă să urmați RAII , duce la creșterea fișierelor executabile, încetinind programele. Dificultăți suplimentare apar în programele paralele și distribuite. În mod semnificativ, standardul de codare C++ al Google interzice în mod expres utilizarea excepțiilor [31] .
  • Codul C++ este mai dificil de înțeles și testat, iar depanarea este mai dificilă prin utilizarea unor ierarhii complexe de clasă cu comportament și moștenire de șablon. În plus, există mai multe erori în mediile de programare C++, atât în ​​compilatoare, cât și în biblioteci.
  • Multe detalii despre comportamentul codului nu sunt specificate de standardul C++, ceea ce afectează portabilitatea și poate cauza erori greu de găsit.
  • Există mult mai mulți programatori calificați în C decât în ​​C++.

Nu există dovezi convingătoare că C++ este superior C, fie în ceea ce privește productivitatea programatorului, fie proprietățile programului. Deși există studii [32] care afirmă că programatorii C petrec aproximativ 30-40% din timpul total de dezvoltare (excluzând depanarea) pentru gestionarea memoriei, atunci când se compară productivitatea generală a dezvoltatorilor [22] , C și C++ sunt apropiate.

În programarea de nivel scăzut, multe dintre noile caracteristici ale C++ sunt inaplicabile din cauza supraîncărcării crescute: funcțiile virtuale necesită calcularea dinamică a adreselor reale (RVA), șabloanele duc la umflarea codului și capabilități slabe de optimizare, biblioteca de rulare (RTL) este foarte mare, iar respingerea acestuia privează majoritatea caracteristicilor C++ (fie doar din cauza indisponibilității new/ operațiunilor delete). Ca urmare, programatorul va trebui să se limiteze la funcționalitatea moștenită de la C, ceea ce face inutilă utilizarea C++:

… singura modalitate de a avea un C++ bun, eficient, de nivel scăzut și portabil este să te limitezi la toate lucrurile care sunt trivial disponibile în C. Și limitarea proiectului la C va însemna că oamenii nu îl vor arunca și că vor fi o mulțime de programatori disponibili care înțeleg bine caracteristicile de nivel scăzut și nu le abandonează din cauza „modelului obiectului” idiot. Prostii.
… când eficiența este primordială, „avantajele” C++ vor fi o mare greșeală.

Linus Torvalds , [33]

C++ și limbaje funcționale și de scripting

Într-un experiment [22] , limbajele de scripting și funcționale, în special Haskell , au arătat un câștig de 2-3 ori în timpul de programare și dimensiunea codului în comparație cu programele C++. Pe de altă parte, programele C++ s-au dovedit a fi la fel de mult mai rapide. Autorii recunosc că datele lor nu constituie un eșantion reprezentativ și se abțin de la a face concluzii categorice.

Într-un alt experiment [34] , limbaje funcționale stricte ( Standard ML , OCaml ) au arătat o accelerare generală a dezvoltării cu un factor de 10 (în principal din cauza detectării timpurii a erorilor) cu indicatori de performanță aproximativ egali (mulți compilatori în mai multe moduri au fost folosit).

Într-un studiu realizat de Lutz Prehelt [24] , pe baza rezultatelor prelucrării a circa 80 de soluții scrise de voluntari, s-au obținut următoarele concluzii, în special:

  • Perl, Python, Rexx, Tcl au oferit o viteză de dezvoltare de două ori mai mare decât C, C++ și Java, iar codul rezultat a fost, de asemenea, jumătate mai lung.
  • Programele din limbaje de scripting consumau aproximativ de două ori mai multă memorie decât C/C++

Critica

Despre critica C++ în general

Cel mai adesea, criticii nu opun C++ oricărui alt limbaj specific, dar susțin că respingerea utilizării unui singur limbaj care are numeroase defecte în favoarea descompunerii unui proiect în subsarcini care pot fi rezolvate în diferite limbi care sunt cele mai potrivite pentru ele fac dezvoltarea mult mai puțin consumatoare de timp, îmbunătățind în același timp indicatorii de calitate a programării [35] [36] . Din același motiv, menținerea compatibilității cu C este criticată: dacă o parte a sarcinii necesită caracteristici de nivel scăzut, este mai rezonabil să separați această parte într-un subsistem separat și să o scrieți în C.

La rândul lor, susținătorii C++ susțin că eliminarea problemelor tehnice și organizatorice ale interacțiunii interlingvistice prin utilizarea unei singure limbi universale în locul mai multor limbi specializate este mai importantă decât pierderile din imperfecțiunea acestui limbaj universal, adică foarte lărgimea setului de caracteristici C ++ este o scuză pentru deficiențele fiecărei caracteristici individuale; inclusiv dezavantajele moștenite de la C sunt justificate de avantajele compatibilității (vezi mai sus ).

Astfel, aceleași proprietăți ale C++ - volumul, complexitatea, eclectismul și lipsa unei nișe țintă specifice de aplicare - sunt considerate de susținători drept „ principalul avantaj ”, iar de critici – ca „ principalul dezavantaj ”.

Critica elementelor și conceptelor individuale

Controlul comportamentului

Ideologia limbajului confundă „ controlul comportamentului ” cu „ controlul eficienței ”: principiul „ nu plătești pentru ceea ce nu folosești ” sugerează că oferirea programatorului control complet asupra tuturor aspectelor execuției programului la un nivel destul de scăzut este o condiție necesară și suficientă pentru a obține o eficiență ridicată a codului. De fapt, acest lucru nu este adevărat pentru niciun program mare: impunerea de optimizare la nivel scăzut asupra programatorului, pe care un compilator de limbaj specific domeniului de înaltă calitate este evident capabil să o execute mai eficient, duce doar la o creștere a cantității de cod, o creștere a intensității muncii de programare și o scădere a înțelegerii și testabilității codului. Astfel, principiul „nu plăti pentru ceea ce nu se folosește” nu oferă cu adevărat beneficiile dorite în eficiență, dar afectează negativ calitatea.

Programare orientată pe componente și pe obiecte

Potrivit lui Alan Kay , modelul obiect „ Algol cu ​​clase” folosit în C++ este inferior modelului „totul este un obiect” [37] utilizat în Objective-C în ceea ce privește domeniul general, reutilizarea codului , înțelegerea, modificarea și testabilitatea. .

Modelul de moștenire C++ este complex, greu de implementat și provoacă în același timp crearea de ierarhii complexe cu relații nefirești între clase (de exemplu, moștenire în loc de imbricare). Rezultatul este crearea unor clase strâns cuplate , cu funcționalități vag separate. De exemplu, în [38] este dat un exemplu educațional și de recomandare de implementare a clasei „listă” ca subclasă a clasei „element listă”, care, la rândul său, conține funcții de acces pentru alte elemente de listă. Această relație de tip este matematic absurdă și ireproductibilă în limbaje mai riguroase. Ideologia unor biblioteci necesită introducerea manuală a tipurilor în sus și în jos în ierarhia claselor ( static_castși dynamic_cast), ceea ce încalcă siguranța tipului a limbajului. Vâscozitatea ridicată a soluțiilor C++ poate necesita redezvoltarea unor părți mari din proiect cu modificări minime mai târziu în procesul de dezvoltare. Un exemplu viu de astfel de probleme poate fi găsit în [35]

După cum subliniază Ian Joyner [39] , C++ echivalează în mod eronat încapsularea (adică introducerea datelor în interiorul obiectelor și separarea implementării de interfață) și ascunderea implementării. Acest lucru complică accesul la datele clasei și necesită ca interfața acesteia să fie implementată aproape exclusiv prin funcții accesorii (care, la rândul lor, mărește cantitatea de cod și o complică).

Potrivirea tipurilor în C++ este definită la nivel de identificatori, nu de semnături. Acest lucru face imposibilă înlocuirea componentelor pe baza potrivirii interfeței, motiv pentru care includerea de noi funcționalități implementate la nivel de bibliotecă în sistem necesită modificarea manuală a codului existent [40] . După cum subliniază Linus Torvalds [33] , în C++, „Codul pare abstract doar atâta timp cât nu trebuie schimbat”.

Critica C++ din punctul de vedere al OOP este dată în [39] .

Metaprogramare

Metaprogramarea generativă a C++ este bazată pe șablon și preprocesor , necesită multă muncă și are un domeniu limitat. Sistemul de șabloane C++ este de fapt o variantă în timp de compilare a limbajului de programare funcțional primitiv. Acest limbaj nu are aproape nicio suprapunere cu C++ în sine, motiv pentru care potențialul de creștere a complexității abstracțiilor este limitat. Programele care folosesc șabloane C++ au o înțelegere și testabilitate extrem de slabe, iar dezasamblarea șablonului în sine generează cod ineficient, deoarece limbajul șablonului nu oferă niciun mijloc de optimizare (vezi și secțiunea #Eficiență computațională ). Limbajele încorporate specifice domeniului implementate în acest mod necesită încă cunoștințe despre C++ în sine, care nu oferă o diviziune completă a muncii. Astfel, capacitatea C++ de a extinde capabilitățile C++ în sine este destul de limitată [41] [42] .

Multiplatformă

Scrierea codului C++ portabil necesită o mare abilitate și experiență, iar codul C++ „neînsăcit” este foarte probabil să fie neportabil [43] . Potrivit lui Linus Torvalds , pentru a obține o portabilitate C++ similară cu C, programatorul trebuie să se limiteze la caracteristicile C++ moștenite din C [33] . Standardul conține multe elemente definite ca „definite de implementare” (de exemplu, dimensiunea pointerilor către metodele de clasă în diferite compilatoare variază de la 4 la 20 de octeți [44] ), ceea ce înrăutățește portabilitatea programelor care le folosesc.

Natura directivă a standardizării limbajului , compatibilitatea incompletă cu înapoi și inconsecvența cerințelor diferitelor versiuni ale standardului duc la probleme în portarea programelor între compilatoare diferite și chiar versiuni ale acelorași compilatoare.

Lipsa oportunităților

Metaprogramarea reflexivă Introspecția în C++ este implementată separat de sistemul de tip principal, ceea ce îl face aproape inutil. Cel mai mare lucru care poate fi obținut este parametrizarea comportamentului pe un set de opțiuni cunoscut anterior. Acest lucru împiedică utilizarea C++ în majoritatea abordărilor de implementare a inteligenței artificiale . Programare functionala Suportul explicit pentru programarea funcțională este prezent doar în standardul C++0x , anterior golul era umplut de biblioteci ( Loki , Boost ) care folosesc limbajul șablon, dar calitatea lor este semnificativ inferioară soluțiilor construite în limbaje funcționale [explicații] 1] , precum și calitatea implementărilor caracteristicilor C++ (cum ar fi OOP) prin limbaje funcționale. Capacitățile FP implementate în C++ nu permit utilizarea tehnicilor de optimizare inerente programării funcționale , dar se limitează la apelarea bibliotecilor funcționale și implementarea metodelor individuale. Acest lucru are puțin sau deloc avantaj în proiectarea programului (vezi corespondența Curry-Howard ).

Oportunități redundante și periculoase

Bypass-uri încorporate

Limbajul conține instrumente care permit programatorului să încalce disciplina de programare dată într-un anumit caz. De exemplu, un modificator constsetează proprietatea de imuabilitate a stării pentru un obiect, dar modificatorul mutableeste conceput special pentru a forța permisiunea de a schimba starea în interiorul unui obiect const, adică pentru a încălca constrângerea constness. Mai mult, este permisă eliminarea dinamică a unui atribut constdintr-un obiect constant, transformându-l într-o valoare L. Prezența unor astfel de caracteristici în limbaj face ca încercările de a verifica oficial codul să fie lipsite de sens, iar utilizarea restricțiilor pentru optimizare este imposibilă.

Înlocuire macro necontrolată

Facilitățile de substituție macro C ( #define) sunt pe cât de puternice, pe atât de periculoase. Ele sunt reținute în C++ în ciuda faptului că, pentru toate sarcinile pentru care au fost furnizate în C, C++ a oferit facilități mai stricte și specializate - șabloane, supraîncărcare de funcții, funcții inline, spații de nume, tastare mai avansată, extensie a aplicației modificatorul const. , etc. Există multe macrocomenzi potențial periculoase în bibliotecile standard moștenite de la C [45] . Metaprogramarea șablonului este, de asemenea, uneori combinată cu utilizarea substituției macro pentru a oferi așa-numitele. „ zahăr sintactic ”.

Probleme de supraîncărcare

Principiile C++ ale supraîncărcării funcțiilor și operatorilor conduc la o duplicare semnificativă a codului. Intenționat inițial să introducă așa-numitul „ zahăr sintactic ”, supraîncărcarea operatorilor în C++ încurajează comportamentul necontrolat al operatorilor elementari pentru diferite tipuri. Acest lucru crește dramatic riscul de erori, mai ales că este imposibil să se introducă o nouă sintaxă și să se schimbe pe cea existentă (de exemplu, crearea de noi operatori sau modificarea priorităților sau asociativității), deși sintaxa operatorilor standard C++ este adecvată semantică de departe de toate tipurile care ar putea trebui introduse în program. Unele probleme sunt create de posibilitatea supraîncărcării ușoare a operatorilor / , care poate genera erori extrem de insidioase și greu de găsit. În același timp, unele operații așteptate intuitiv (curățarea obiectelor dinamice în cazul aruncării de excepții) nu sunt efectuate în C++, iar o parte semnificativă a funcțiilor și operatorilor supraîncărcați sunt chemați implicit (casting de tip, crearea de instanțe temporare de clase etc. .). Ca rezultat, instrumentele inițial destinate să clarifice programele și să îmbunătățească dezvoltarea și mentenabilitatea devin încă o sursă de cod inutil de complicat și nesigur. newdelete

Eficiență computațională

Cantitatea rezultată de cod executabil

Utilizarea șabloanelor C++ este un polimorfism parametric la nivel de cod sursă, dar atunci când este tradus, se transformă într -un polimorfism ad-hoc (adică supraîncărcare de funcții), ceea ce duce la o creștere semnificativă a cantității de cod mașină în comparație cu limbile care au un adevărat sistem de tip polimorf (descendenții lui ML ). Pentru a reduce dimensiunea codului de mașină, ei încearcă să proceseze automat codul sursă înainte de etapa de derulare a șabloanelor [46] [47] . O altă soluție ar putea fi posibilitatea de a exporta șabloane, care a fost standardizată încă din 1998, dar nu este disponibilă în toate compilatoarele, deoarece este dificil de implementat [48] [49] [opinii 4] și pentru importarea bibliotecilor de șabloane C++ în limbi cu o semantică C++ semnificativ diferită, ar fi încă inutil. Susținătorii C++ contestă gradul de umflare a codului ca fiind exagerat [50] , ignorând chiar faptul că în C polimorfismul parametric este tradus direct, adică fără a dubla corpuri de funcții deloc. În același timp, susținătorii C++ consideră că polimorfismul parametric în C este periculos - adică mai periculos decât trecerea de la C la C++ (oponenții lui C++ susțin contrariul - vezi mai sus).

Potenţial de optimizare

Datorită sistemului de tip slab și abundenței efectelor secundare , devine extrem de dificilă convertirea echivalentă a programelor și, prin urmare, încorporarea multor algoritmi de optimizare în compilator, cum ar fi paralelizarea automată a programelor , eliminarea subexpresiilor comune , λ-lifting, apeluri la proceduri cu trecere în continuare , supercompilare , etc. Ca urmare, eficiența reală a programelor C++ este limitată de abilitățile programatorilor și de eforturile investite într-un anumit proiect, iar o implementare „neîncetată” poate fi semnificativ inferioară ca eficiență față de „neîncetată”. ” implementări în limbi de nivel superior, ceea ce este confirmat de teste comparative de limbi [34] . Aceasta este o barieră semnificativă împotriva utilizării C++ în industria data mining .

Gestionare eficientă a memoriei

Responsabilitatea pentru gestionarea eficientă a memoriei cade pe umerii dezvoltatorului și depinde de abilitățile dezvoltatorului. Pentru gestionarea automată a memoriei în C++, așa-numita. „indicatoare inteligente”, gestionarea manuală a memoriei reduce eficiența programatorilor înșiși (a se vedea secțiunea Eficiență ) . Numeroase implementări de colectare a gunoiului , cum ar fi inferența statică a regiunilor , nu sunt aplicabile pentru programele C++ (mai precis, acest lucru necesită implementarea unui nou interpret de limbaj pe lângă limbajul C++, care este foarte diferit de C++ atât în ​​majoritatea proprietăților obiective). și în general ideologie) datorită necesității de acces direct la AST .

Eficiență

Corelarea factorilor de performanță cu costurile de dezvoltare, precum și disciplina generală și cultura de programare cultivată în comunitatea de programare, sunt importante pentru clienții care aleg un limbaj (și, în consecință, preferă acest limbaj al dezvoltatorilor) pentru implementarea proiectelor lor, precum și pentru persoanele care încep să învețe programarea, mai ales cu intenția de a programa pentru propriile nevoi.

Calitatea și cultura programării

Principiul C++ „ de a nu impune un „stil „bun” de programare ” este contrar abordării industriale a programării, în care rolul principal îl joacă calitatea software-ului și posibilitatea menținerii codului nu numai de către autor. și pentru care se preferă limbaje care minimizează influența factorului uman , adică doar „ impunerea unui stil „bun” de programare ”, deși astfel de limbaje pot avea un prag de intrare mai mare.

Există o părere că preferința pentru utilizarea C++ (cu posibilitatea de a alege limbaje alternative) caracterizează negativ calitățile profesionale ale unui programator. Mai exact, Linus Torvalds spune că folosește opiniile pozitive ale candidaților despre C++ ca criteriu de abandon [opinii 3] :

C++ este un limbaj teribil. Ceea ce îl face și mai îngrozitor este faptul că o mulțime de programatori nealfabetizați îl folosesc... Sincer, chiar dacă nu există niciun motiv pentru a alege C, în afară de a-i ține departe pe programatorii C++, doar acesta ar fi un motiv suficient de bun pentru a utiliza C.
…Am ajuns la concluzia că aș prefera să dau afară pe oricine ar prefera să dezvolte un proiect în C++ decât în ​​C, astfel încât această persoană să nu strice proiectul în care sunt implicat.

Linus Torvalds , [33] Remedierea unui defect

Evoluția continuă a limbajului încurajează (și uneori forțează) programatorii să schimbe din nou și din nou codul deja depanat - acest lucru nu numai că crește costul dezvoltării, dar implică și riscul introducerii de noi erori în codul depanat. În special, deși compatibilitatea cu C++ a fost inițial unul dintre principiile de bază ale C++, din 1999 C a încetat să mai fie un subset al C++, astfel încât codul C depanat nu mai poate fi folosit într-un proiect C++ fără modificări.

Complexitatea de dragul ei

C++ este definit de apologeții săi drept „cel mai puternic” tocmai pentru că este plin de caracteristici periculoase, reciproc contradictorii. Potrivit lui Eric Raymond , acest lucru face din limbajul în sine un teren pentru autoafirmarea personală a programatorilor, transformând procesul de dezvoltare într-un scop în sine:

Programatorii sunt adesea indivizi extravaganți care se mândresc cu... capacitatea lor de a gestiona complexitatea și de a gestiona abstracțiile cu dexteritate. Adesea ei concurează între ei, încercând să-și dea seama cine poate crea „cele mai complicate și frumoase complexități”. ... rivalii cred că trebuie să concureze cu „decorurile” altora adăugându-le pe ale lor. Destul de curând, „tumoarea masivă” devine standardul industriei și toată lumea rulează programe mari, cu probleme pe care nici măcar creatorii lor nu le pot satisface.

… această abordare poate avea probleme dacă programatorii fac lucruri simple în moduri complexe, pur și simplu pentru că știu acele moduri și știu cum să le folosească.

Eric Raymond la [51] Sabotaj

Au fost observate cazuri când programatorii neglijenți, folosind dependența puternică de context a C ++ și lipsa capacității de a urmări definițiile macro de către compilator, au încetinit dezvoltarea proiectului scriind unul sau două în plus, corecte din punctul de vedere al compilatorului. de vedere, linii de cod, dar introducerea unei erori greu de detectat manifestată spontan pe cheltuiala lor. De exemplu:

#define if(a) if(rand())


#define ji

În limbile cu corectitudine dovedită , chiar și cu facilități macro avansate, este imposibil să faci daune în acest fel.

Produs nesigur

O abundență nerezonabilă de efecte secundare, combinată cu o lipsă de control din partea sistemului de rulare al limbajului și un sistem de tip slab, face ca programele C++ să fie predispuse la blocări fatale imprevizibile (cele binecunoscute blocări cu mesaje precum „Încălcarea accesului”, „Funcția virtuală pură apel” sau „Programul a efectuat o operațiune ilegală și va fi închis”), ceea ce exclude utilizarea C++ cu cerințe ridicate pentru toleranța la erori. În plus, crește durata procesului de dezvoltare în sine [34] .

Management de proiect

Factorii enumerați mai sus fac din complexitatea managementului de proiect C++ una dintre cele mai înalte din industria dezvoltării software.

James Coggins, un cronicar de patru ani pentru The C++ Report , explică:
 Problema este că programatorii OOP au experimentat cu aplicații incestuoase și au urmărit un nivel scăzut de abstractizare. De exemplu, au construit clase precum „listă legată” în loc de „interfață cu utilizatorul” sau „faz de radiație” sau „model cu elemente finite”. Din păcate, verificarea puternică a tipurilor, care îi ajută pe programatorii C++ să evite erorile, face și mai dificilă construirea de obiecte mari din cele mici.

F. Brooks , Omul mitic-luna

Influență și alternative

Singurul descendent direct al C++ este limbajul D , menit să fie o reelaborare a C++ pentru a rezolva problemele sale cele mai evidente. Autorii au abandonat compatibilitatea cu C, păstrând sintaxa și multe dintre principiile de bază ale C++ și introducând în limbaj caracteristici care sunt caracteristice noilor limbi. D nu are preprocesor, nu are fișiere de antet, nu are moștenire multiplă, ci un sistem de module, interfețe, matrice asociative, suport pentru unicode în șiruri de caractere, colectare de gunoi (în timp ce se menține posibilitatea de gestionare manuală a memoriei), multithreading încorporat, inferență de tip , declararea explicită a funcțiilor pure și a valorilor imuabile. Utilizarea lui D este foarte limitată, nu poate fi considerat un concurent real al C++.

Cel mai vechi competitor al C++ în sarcinile de nivel scăzut este Objective-C , construit tot pe principiul combinării C cu un model obiect, doar modelul obiect fiind moștenit de la Smalltalk . Objective-C, ca și descendentul său Swift , este utilizat pe scară largă pentru dezvoltarea de software pentru macOS și iOS.

Una dintre primele alternative la C++ în programarea aplicațiilor a fost limbajul Java . Este adesea considerat eronat un descendent direct al C++; de fapt, semantica Java este moștenită din limbajul Modula-2 , iar semantica de bază a C++ nu poate fi urmărită în Java. Având în vedere acest lucru și genealogia limbilor (Modula-2 este un descendent al Simula , ca C++, dar nu este C), Java este mai corect numit „ vărul secund ” al C++, mai degrabă decât „ moștenitorul ”. Același lucru se poate spune despre limbajul C# , deși procentul de afinitate cu C++ este puțin mai mare decât cel al Java.

O încercare de a combina securitatea și viteza de dezvoltare a Java și C# cu capabilitățile C++ a fost dialectul C++ gestionat (mai târziu C++/CLI ). A fost dezvoltat de Microsoft în primul rând pentru a porta proiectele C++ existente pe platforma Microsoft .NET. Programele rulează sub CLR și pot folosi întreaga gamă de biblioteci .NET, dar există o serie de restricții privind utilizarea caracteristicilor C++, care reduc efectiv C++ la C#. Acest dialect nu a primit o recunoaștere largă și este folosit în principal pentru a lega biblioteci scrise în C++ pur cu aplicațiile C #.

O modalitate alternativă de dezvoltare a limbajului C este de a-l combina nu cu programarea orientată pe obiecte, ci cu programarea aplicativă , adică îmbunătățirea abstracției, rigoarea și modularitatea programelor de nivel scăzut, oferind un comportament previzibil și transparență referențială . Exemple de lucru în acest sens sunt limbile BitC , Cyclone și Limbo . Deși există și încercări de succes de a utiliza FP în probleme în timp real fără integrare cu instrumente C [52] [53] [54] , încă în momentul de față (2013) în dezvoltare la nivel scăzut, utilizarea instrumentelor C într-o oarecare măsură are un raport mai bun intensitatea muncii cu eficienta. Dezvoltatorii Python și Lua au depus mult efort în Python și Lua pentru a se asigura că aceste limbaje sunt folosite de programatorii C++, astfel încât dintre toate limbajele care sunt strâns legate de FP, acestea sunt cele mai des notat că este utilizat împreună cu C++ în același proiect. Cele mai semnificative puncte de contact dintre C++ și FP sunt legăturile bibliotecilor wxWidgets și Qt dezvoltate în C++ cu o ideologie specifică C++ la Lisp , Haskell și Python (în majoritatea cazurilor, legăturile la limbaje funcționale sunt făcute pentru bibliotecile scrise în C sau alte limbaje funcționale).

Un alt limbaj considerat un concurent pentru C++ este Nemerle , care este rezultatul unei încercări de a combina modelul de tastare Hindley-Milner și un subset macro al Common Lisp cu C# [55] . În aceeași ordine de idei este F# de la Microsoft  , un dialect al ML adaptat pentru mediul .NET.

O încercare de a crea un înlocuitor industrial pentru C/C++ a fost limbajul de programare Go dezvoltat de Google în 2009 . Autorii limbajului subliniază în mod direct că motivul creării sale au fost deficiențele procesului de dezvoltare cauzate de particularitățile limbajelor C și C++ [56] . Go este un limbaj imperativ compact, necomplicat, cu sintaxă asemănătoare C, fără preprocesor, tastare statică, tastare puternică, sistem de ambalare, management automat al memoriei, unele caracteristici funcționale, subsistem OOP construit economic fără suport pentru moștenirea implementării, dar cu interfețe și tastare duck , multithreading încorporat bazat pe coroutine și țevi (a-la Occam ). Limbajul este poziționat ca o alternativă la C++, adică, în primul rând, un mijloc de dezvoltare în grup a sistemelor de calcul extrem de complexe, inclusiv distribuite, permițând, dacă este necesar, programarea la nivel scăzut.

În aceeași nișă ecologică cu C/C++ se află Rust, dezvoltat în 2010 și întreținut de Mozilla Corporation , axat pe gestionarea sigură a memoriei fără utilizarea unui colector de gunoi . În special, planurile de a înlocui parțial C/C++ cu Rust au fost anunțate în 2019 de Microsoft [57] .

Vezi și

Note

  1. ISO/IEC 14882:2020 Limbaje de programare - C++ - 2020.
  2. Gubina G. G. Computer English. Partea I. Engleza computerului. Partea I. Tutorial . — P. 385. Arhivat 3 decembrie 2017 la Wayback Machine
  3. Întrebările frecvente ale lui Bjarne Stroustrup  . Bjarne Stroustrup (1 octombrie 2017). - „Numele C++ (pronunțat „vezi plus plus”)”. Data accesului: 4 decembrie 2017. Arhivat din original pe 6 februarie 2016.
  4. Schildt, 1998 .
  5. 1 2 Stroustrup, 1999 , 2.1. Ce este C++?, p. 57.
  6. Stanley Lippman, Pure C++: Hello, C++/CLI Arhivat 6 iunie 2011 la Wayback Machine 
  7. 1 2 Stroustrup, 1999 , 1.4. Observații istorice, p. 46.
  8. C++-Standarde . Consultat la 14 noiembrie 2010. Arhivat din original pe 20 noiembrie 2010.
  9. Bjarne Stroustrup. Glosar C++ (link indisponibil) . Consultat la 8 iunie 2007. Arhivat din original la 1 mai 2011. 
  10. Unde găsesc documentele standard C sau C++ actuale? http://stackoverflow.com/questions/81656/where-do-i-find-the-current-c-or-c-standard-documents Arhivat 29 noiembrie 2015 la Wayback Machine
  11. Vezi o listă la http://en.cppreference.com/w/cpp/experimental Arhivat 18 noiembrie 2015 la Wayback Machine vizitat 5 ianuarie 2015.
  12. Yandex organizează un grup de lucru pentru standardizarea limbajului C++ . ICS Media. Preluat la 29 august 2018. Arhivat din original la 29 august 2018.
  13. Stroustrup, The Design and Evolution of C++, 2007 .
  14. ISO/IEC 14882:1998, secțiunea 6.4, clauza 4: „Valoarea unei condiții care este o declarație inițializată într-o instrucțiune, alta decât o switchinstrucțiune, este valoarea variabilei declarate convertită implicit în bool... Valoarea unei condiții care este o expresie este valoarea expresiei, implicit convertită în boolpentru instrucțiuni altele decât switch; dacă acea conversie este prost formată, programul este prost format”.
  15. STLport: Bun venit! . Preluat la 26 iulie 2007. Arhivat din original la 7 iunie 2018.
  16. Stroustrup, 1999 , 1.6.
  17. std::vector - cppreference.com . Data accesului: 28 noiembrie 2015. Arhivat din original pe 27 noiembrie 2015.
  18. std::realloc - cppreference.com . Data accesului: 28 noiembrie 2015. Arhivat din original pe 4 decembrie 2015.
  19. B. Stroustrup interviu cu LinuxWorld.com . Consultat la 4 ianuarie 2013. Arhivat din original pe 27 ianuarie 2013.
  20. Interviul lui B. Stroustrup cu revista System Administrator . Data accesului: 4 ianuarie 2013. Arhivat din original pe 9 februarie 2013.
  21. CNews: Interviu exclusiv cu creatorul limbajului de programare C++ (link nu este disponibil) . Preluat la 1 noiembrie 2019. Arhivat din original la 17 martie 2015. 
  22. 1 2 3 4 Un experiment în productivitatea prototipurilor software. Paul Hudak, Mark P. Jones. Universitatea Yale, Departamentul de Informatică, New Haven, CT 06518. 4 iulie 1994.
  23. K. Czarnecki, J. O'Donnell, J. Striegnitz, W. Taha. Implementarea DSL în metaocaml, template haskell și C++ . — Universitatea din Waterloo, Universitatea din Glasgow, Centrul de cercetare Julich, Universitatea Rice, 2004. Arhivat din original pe 7 aprilie 2022. .
    Citat: Metaprogramarea șabloanelor C++ suferă de o serie de limitări, inclusiv probleme de portabilitate din cauza limitărilor compilatorului (deși acest lucru s-a îmbunătățit semnificativ în ultimii câțiva ani), lipsa suportului de depanare sau IO în timpul instanțierii șablonului, timpi lungi de compilare, erori lungi și de neînțeles , lizibilitate slabă a codului și raportare slabă a erorilor.
  24. 1 2 3 Lutz Prechelt ( Universität Karlsruhe ). O comparație empirică a C, C++, Java, Perl, Python, Rexx și Tcl pentru un program de căutare/procesare a șirurilor  ( pdf) Freie Universität Berlin (14 martie 2000). Preluat la 20 noiembrie 2019. Arhivat din original la 3 ianuarie 2020.
  25. Ada, C, C++ și Java vs. The Steelman" David A. Wheeler iulie/august 1997 (link nu este disponibil) . Preluat la 23 martie 2019. Arhivat din original la 23 martie 2019. 
  26. 1 2 „O comparație a limbajelor de programare comune utilizate în bioinformatică” . Preluat la 2 septembrie 2021. Arhivat din original la 2 septembrie 2021.
  27. Compararea limbajelor de programare în implementarea algoritmilor bioinformatici - descrierea experimentului. . Preluat la 2 septembrie 2021. Arhivat din original la 2 septembrie 2021.
  28. Comparația caracteristicilor Ada și C++ (en) . Preluat la 23 martie 2019. Arhivat din original la 23 martie 2019.
  29. Stephen Zeigler, Comparing Development Costs of C and Ada. Arhivat din original pe 4 aprilie 2007.
  30. 1.2 Obiectivele de proiectare ale limbajului de programare Java™ .  Mediul limbajului Java . Oracle (1 ianuarie 1999) . Consultat la 14 ianuarie 2013. Arhivat din original pe 23 ianuarie 2013.
  31. Ghidul de stil Google C++. Excepții. . Preluat la 31 martie 2019. Arhivat din original la 16 martie 2019.
  32. Boehm H. Avantajele și dezavantajele colectării conservatoare a gunoiului . Arhivat din original pe 24 iulie 2013.
    (link de la Raymond, Eric . Arta programării Unix. - 2005. - p. 357. - 544 p. - ISBN 5-8459-0791-8 . )
  33. 1 2 3 4 Deschide corespondența gmane.comp.version-control.git din 09/06/2007 (link inaccesibil) . Preluat la 5 august 2013. Arhivat din original la 9 decembrie 2013. 
  34. 1 2 3 Comparația limbajului Ray Tracer (etalon de referință al limbajelor de programare - ffconsultancy.com/languages/ray_tracer/)
  35. 12 Martin Ward . Programare orientată pe limbaj . - Departamentul de informatică, Science Labs, 1994. Arhivat din original pe 4 martie 2016.
  36. Paul Hudak. Limbaje și instrumente modulare specifice domeniului. — Departamentul de Informatică, Universitatea Yale.
  37. Definiția lui Alan Kay a programarii orientate pe obiecte (link nu este disponibil) . Data accesului: 5 august 2013. Arhivat din original pe 24 august 2013. 
  38. Schildt, Teoria și practica C++, 1996 , p. 64-67.
  39. 12 Ian Joyner . O critică a C++ și a tendințelor de programare și limbaj din anii 1990 - ediția a treia . - drepturile de autor și lista publicațiilor . Arhivat din original pe 25 noiembrie 2013.
  40. Paulson, Lawrence C. ML for the Working Programmer, ediția a 2-a. - Universitatea din Cambridge: Cambridge University Press, 1996. - ISBN 0-521-57050-6 (copertă cartonată), 0-521-56543-X (copertă). , c.271-285
  41. Walid Taha. Limbi specifice domeniului . — Departamentul de Informatică, Universitatea Rice. Arhivat din original pe 24 octombrie 2013.
  42. Lugovsky VS Utilizarea unei ierarhii de limbaje specifice domeniului în proiectarea sistemelor software complexe . - 2008. Arhivat la 10 august 2016.
  43. Andrei Karpov. 20 Capcane ale portarii codului C++ pe o platformă pe 64 de biți . - RSDN Magazine #1-2007, 2007. Arhivat din original pe 2 aprilie 2015.
  44. Don Clugston, CSG Solar Pty Ltd (Trad. de Denis Bulichenko). Indicatori pentru funcția membru și cea mai rapidă implementare C++ a delegaților . — Revista RSDN #6-2004. Arhivat din original pe 19 octombrie 2013.
  45. ^ Stroustrup , Programming: C++ Principles and Practice, 2001
  46. Dave Gottner. Șabloane fără cod umflare . — Dr. Dobb's Journal , ianuarie 1995. Arhivat din original pe 7 iunie 2008.
  47. Adrian Stone. Minimizarea bloat-ului de cod: instanțierea șabloanelor redundante (link descendent) . Game Angst (22 septembrie 2009). Data accesului: 19 ianuarie 2010. Arhivat din original la 8 decembrie 2011. 
  48. Herb Sutter . Breviar privind conformitatea C++ . — Dr. Dobb's Journal , ianuarie 2001. Arhivat din original pe 15 ianuarie 2009.
  49. Există compilatoare care implementează toate acestea? (link indisponibil) . comp.std.c++ întrebări frecvente / Limbajul C++ . Comeau Computing (10 decembrie 2008). Data accesului: 19 ianuarie 2010. Arhivat din original la 30 aprilie 2009. 
  50. Scott Meyers . Cod Bloat din cauza șabloanelor . comp.lang.c++.moderat . Usenet (16 mai 2002). Preluat: 19 ianuarie 2010.
  51. Eric Raymond . Arta de a programa pentru Unix = Arta Unix. - Williams, 2005. - ISBN 5-8459-0791-8 .
  52. Zhanyong Wan și Paul Hudak. FRP bazat pe evenimente  // Departamentul de Informatică, Universitatea Yale. Arhivat din original pe 16 august 2011.
  53. Walid Taha  (engleză)  (link nu este disponibil) . Scoala de Inginerie Universitatea Rice . Preluat la 20 noiembrie 2019. Arhivat din original la 13 august 2013.
  54. MLKit (link descendent) . Consultat la 30 iulie 2013. Arhivat din original la 17 septembrie 2013. 
  55. Chistyakov Vlad aka VladD2. Zahar sintactic sau C++ vs. Nemerle :)  // Revista RSDN #1-2006. - 24.05.2006. Arhivat din original pe 13 decembrie 2013.
  56. Accesați Google: Language Design in the Service of Software Engineering . talks.golang.org. Preluat la 19 septembrie 2017. Arhivat din original la 25 ianuarie 2021.
  57. Cătălin Cimpanu. Microsoft va explora folosind Rust  . ZDNet (17 iunie 2019). Preluat la 26 septembrie 2019. Arhivat din original la 15 octombrie 2019.
Opinii
  1. Popularitatea limbajului de programare (link inaccesibil) (2009). Data accesului: 16 ianuarie 2009. Arhivat din original la 16 ianuarie 2009. 
  2. Indexul comunității de programare TIOBE (link indisponibil) (2009). Consultat la 6 mai 2009. Arhivat din original pe 4 mai 2009. 
  3. 1 2 Deschideți corespondența gmane.comp.version-control.git din 09/06/2007 (link inaccesibil) . Preluat la 5 august 2013. Arhivat din original la 9 decembrie 2013. 
  4. vanDooren. Cuvântul cheie C++ al zilei: export (link indisponibil) . Blogs@MSMVPs (24 septembrie 2008). „Cuvântul cheie de export este un pic ca bosonul Higgs al C++. Teoretic există, este descris de standard și nimeni nu l-a văzut în sălbăticie. … Există un front-end de compilator C++ în lume care îl acceptă de fapt.” Data accesului: 19 ianuarie 2010. Arhivat din original la 6 mai 2009. 
Explicații
  1. De exemplu, Boost.Lambdacomercializată ca funcție lambda, dar C++ nu implementează calculul lambda al lui Church în întregime; imitarea combinatorilor printr-un limbaj șablon este prea dificilă pentru a ne aștepta la utilizarea lor în practică; continuările moștenite din C sunt considerate neideomatice și periculoase, iar implementarea lor prin limbajul șablon este imposibilă; în plus, utilizarea λ-lifting pentru a optimiza C++ nu este posibilă – deci este de fapt Boost.Lambda doar o funcție anonimă, nu un obiect al calculului lambda.

Literatură

  • Bjorn Stroustrup . Limbajul de programare C++ = The C++ Programming Language / Per. din engleza. - Ed. a 3-a. - Sankt Petersburg. ; M. : Dialectul Nevski - Binom , 1999. - 991 p. - 3000 de exemplare.  — ISBN 5-7940-0031-7 (dialectul Nevsky), ISBN 5-7989-0127-0 (Binom), ISBN 0-201-88954-4 (engleză).
  • Bjorn Stroustrup . limbaj de programare C++. Ediție specială = limbajul de programare C++. ediție specială. - M. : Binom-Press, 2007. - 1104 p. — ISBN 5-7989-0223-4 .
  • Bjorn Stroustrup . Programare: principii și practică folosind C++, ediție revizuită = Programare: principii și practică folosind C++. — M .: Williams , 2011. — S. 1248. — ISBN 978-5-8459-1705-8 .
  • Bjorn Stroustrup . Design and Evolution of C++ = The Design and Evolution of C++. - Sankt Petersburg. : Peter, 2007. - 445 p. — ISBN 5-469-01217-4 .
  • Bjorn Stroustrup . limbaj de programare C++. Curs scurt. - 2019. - 320 p. - ISBN 978-5-907144-12-5 .
  • Bjorn Stroustrup . Programare: principii și practică folosind C++. - 2016. - 1328 p. - ISBN 978-5-8459-1949-6 .
  • Siddhartha Rao. Teach Yourself C++ într-o oră pe zi, ediția a 7-a (C++11) = Sams Teach Yourself C++ într-o oră pe zi, ediția a 7-a. - M. : „Williams” , 2013. - 688 p. — ISBN 978-5-8459-1825-3 .
  • Stephens D. R. C++. Culegere de retete. - KUDITS-PRESS, 2007. - 624 p. - ISBN 5-91136-030-6 .
  • Ştefan Prata. Limbajul de programare C++ (C++11). Prelegeri și exerciții = C++ Primer Plus, ediția a 6-a (Biblioteca dezvoltatorului). - Ed. a VI-a. — M. : Williams , 2012. — 1248 p. - ISBN 978-5-8459-1778-2 .
  • Ştefan Prata. Limbajul de programare C. Prelegeri si exercitii. — M. : Williams , 2015. — 928 p. - ISBN 978-5-8459-1950-2 .
  • Ivor Horton. Visual C ++ 2010: curs complet = Ivor Horton's Beginning Visual C ++ 2010. - M . : Dialectics , 2010. - S. 1216. - ISBN 978-5-8459-1698-3 .
  • Herbert Schildt . Referința completă la C++ = C++: Referința completă. - a 4-a ed. - M .: Williams , 2011. - S. 800. - ISBN 978-5-8459-0489-8 .
  • Herbert Schildt . Teoria și practica C++ = Schildt's Expert C++. - Sankt Petersburg. : BHV - Sankt Petersburg, 1996. - ISBN 0-07-882209-2 , 5-7791-0029-2.
  • PJ Plauger. Jocuri de ghicire în limbaj de programare - Dacă C++ este răspunsul, care este întrebarea? // Dr. Jurnalul lui Dobb . - octombrie 1993.
  • Manualul Unix-Haters  (nedeterminat) . - International Data Group , 1994.
  • Ian Joyner. O critică a C++ și a tendințelor de programare și limbaj din anii 1990 - ediția a 3-a  // drepturi de autor și listă de publicații . — 1996.
  • Scott Meyers. C++ modern eficient: 42 de recomandări pentru utilizarea C++11 și C++14 = C++ modern eficient: 42 de moduri specifice de a îmbunătăți utilizarea C++11 și C++14 / Per. din engleza. - Williams, 2016. - 304 p. - ISBN 978-5-8459-2000-3 .
  • Herbert Schildt . C++ The Complete Reference Ediția a treia. - Osborne McGraw-Hill, 1998. - ISBN 978-0-07-882476-0 .
  • Jeremy A. Hansen Ghidul Rook pentru C++ (un manual cu licență Creative Commons) .

Link -uri

  • isocpp.org ​(  engleză) - site-ul web oficial C++