C++14

C++14  er det uofficielle navn på ISO/IEC JTC1- versionen af ​​C++- standarden (fulde navn: " International Standard ISO/IEC 14882:2014(E) Programming Language C++ ") [1] . C++14 kan opfattes som en lille udvidelse af C++11 , der for det meste indeholder fejlrettelser og mindre forbedringer. New Standard Development Committee offentliggjorde udkast til N3690 den 15. maj 2013 [2] . Arbejdsudkastet N3936 blev offentliggjort den 2. marts 2014, den endelige afstemningsperiode sluttede den 15. august 2014, og resultatet (enstemmig godkendelse) blev offentliggjort den 18. august 2014 [3] .

Da udviklingen af ​​standarden var langvarig, og udgivelsesåret for den endelige version ikke var fastlagt, blev navnet "C++1y" også brugt under udviklingen, svarende til hvordan C++11-standarden blev kaldt "C+ +0x" før udgivelsen (udgivelsen af ​​denne version var forventet indtil 2010).

Sprogfunktionerne beskrevet nedenfor svarer til arbejdsudkastet N3797 . Der kan være små forskelle i disse i forhold til den endelige version af standarden .

Sprogændringer

Dette afsnit introducerer nye kernesprogfunktioner i C++14.

Returtype-inferens for funktioner

C++11 giver dig mulighed for at udlede returtypen for lambda-funktioner fra returtypen for et udtryk. C++14 udvider denne funktion til alle funktioner. Den nye standard beskriver også typeinferens for lambda-funktioner, med en anden form end return expression;[4] .

For at bruge automatisk returtype-inferens skal en funktion erklæres med type autosom returtype, men uden C++11-returtype-halespecifikationen:

auto DeduceReturnType (); // returtype vil blive defineret senere.

Hvis flere udtryk returneres forskellige steder i funktionens krop, skal alle disse udtryk have en fælles udledt type [5] .

Funktioner, der bruger returtype auto-inferens, kan bruge fremadrettet erklæring, men de kan kun bruges, efter at de er blevet defineret. Disse definitioner skal være tilgængelige i den samme oversættelsesenhed, som de bruges i.

Det er muligt at bruge rekursion i sådanne funktioner , men det rekursive kald skal foretages efter mindst én returværdi i denne funktion [5] :

autokorrektur ( int i ) { _ hvis ( i == 1 ) returnere i ; // int vises som en anden returtype return Ret ( i -1 ) + i ; // nu kan du ringe } autoForkert ( int i ) { _ hvis ( i != 1 ) return Forkert ( i -1 ) + i ; // upassende sted for rekursion. Ingen forudgående retur. andet returnere i ; // int vises som returtype }

Alternativ typeslutning ved erklæring af

C++11 tilføjede to måder at udlede typer på. autogav dig mulighed for at oprette variabler med en type baseret på et tildelt udtryk. decltypetilladt at bestemme den resulterende type af et vilkårligt udtryk. Men de typer, der blev udledt af decltypeog autoadskilte sig fra hinanden. Især autoudleder altid en ikke-referencetype, som om den blev behandlet std::remove_reference, mens den auto&&altid udleder en referencetype. Resultatet decltypekan dog enten være en referencetype eller en ikke-referencetype, afhængigt af det udtryk, der behandles [4] :

int i ; int && f (); autox3a = i ; _ // decltype(x3a) - int decltype ( i ) x3d = i ; // decltype(x3d) - int auto x4a = ( i ); // decltype(x4a) - int decltype (( i )) x4d = ( i ); // decltype(x4d) - int& auto x5a = f (); // decltype(x5a) - int decltype ( f ()) x5d = f (); // decltype(x5d) - int&&

C++14 tilføjede syntaksen decltype(auto). Denne syntaks giver dig mulighed for at bruge decltypedeklarationsregler auto. Det giver kun mening i boilerplate-kode.

Syntaksen decltype(auto)kan også bruges til at udlede returtyper ved at angive funktionens returtype decltype(auto)i stedet autofor på plads [5] .

Reduktion af restriktioner på konstante udtryk

C++11 introducerer begrebet constexpr-funktioner: funktioner, der kan udføres på kompileringstidspunktet. De værdier, de returnerer, kan bruges i operationer, der kræver et konstant udtryk, såsom et skabelonargument. Men i C++11 constexprkan -funktioner kun indeholde ét returudtryk (samt static_assertflere andre erklæringer).

I C++14 er disse restriktioner delvist ophævet. constexpr-funktioner kan nu indeholde følgende elementer [4] :

  • Enhver meddelelse bortset fra:
    • staticeller thread_localvariabler;
    • variable erklæringer uden initialisering.
  • Betingede greninstruktioner ifog switch.
  • Alle sløjfeinstruktioner, inklusive dem forfor intervaller.
  • Udtryk, der ændrer værdierne af objekter, hvis levetiden for disse objekter begyndte i constexpr-funktionen. Dette inkluderer også kald til alle ikke const constexpr-statiske medlemsfunktioner.

Udsagnet gotoer ikke tilladt i en constexprC++14 -funktion.

Begrænsninger for opkald til ikke- constexpr-funktioner forbliver i kraft. Hvis de bruges fortil områder, skal funktioner beginog endcontainere således overbelastes som constexpr. For en indbygget type defineres std::initializer_listfunktioner begin/endsom constexpr, både lokalt og globalt.

I C++11 blev alle ikke-statiske metoder erklæret med constexprimplicit behandlet som const-funktioner med hensyn til this. Denne begrænsning er blevet fjernet; ikke-statiske metoder kan nu være ikke- const[6] . Men som tidligere nævnt kan en ikke const constexpr-metode kun ændre klassefelter, hvis objektets levetid begyndte under evalueringen af ​​et konstant udtryk.

Variable skabeloner

I tidligere versioner af C++ var skabelon begrænset til funktioner og klasser. C++14 giver dig mulighed for at oprette skabelonvariabler.

skabelon < typenameT > _ constexpr T pi = T ( 3,1415926535897932385 ); // Sædvanlige specialiseringsregler gælder: skabelon <> constexpr const char * pi < const char *> = "pi" ;

I dette eksempel er der defineret en variabelskabelon, pider kan tilgås for at få værdien af ​​pi for forskellige typer (f.eks. 3når man læser en heltalstype; tættest på float, doubleeller long doublenår man læser henholdsvis som float, doubleeller long double, osv.).

Sådanne erklæringer og definitioner omfatter de sædvanlige skabelonregler, herunder specialiseringsregler [7] [8] .

Samlet initialisering af klasser med feltinitialiserere

C++11 introducerede klassefeltinitialisatorer, som er udtryk, der gælder for felter på klasseniveau, hvis konstruktøren ikke initialiserer dem på egen hånd. Definitionen af ​​aggregater blev ændret for eksplicit at udelukke alle klasser med medlemsinitialiserere, så aggregeret initialisering var ikke mulig for dem.

C++14 fjerner denne begrænsning [4] og tillader aggregeret initialisering af klasser med feltinitialisatorer. Hvis listen over initialisatorer i krøllede klammer ikke giver en værdi for dette argument, så overtager feltinitialisatoren [9] .

Binære bogstaver

Numeriske bogstaver i C++14 kan angives i binær form [4] . Syntaksen bruger præfikserne 0beller 0B. Lignende syntaks bruges også i Java , Python , Perl og D.

Tusind adskillere

I C++14 kan du bruge apostrof til vilkårligt at adskille bits i numeriske bogstaver [10] . I nogle tilfælde forenkler dette opfattelsen af ​​store numeriske konstanter i koden og forbedrer kodens læsbarhed.

auto heltal_literal = 1'000'000 ; auto floating_point_literal = 0,000'015'3 ; auto binær_bogstav = 0b0100'1100'0110 ; auto fjollet_eksempel = 1'0'0'000'00 ;

Generiske lambda-funktioner

I C++11 skulle lambda-funktionsparametre deklareres med specifikke typer. C++14 fjerner denne begrænsning og tillader lambda-funktionsparametre at blive erklæret med en typespecifikation auto[7] .

auto lambda = []( auto x , auto y ) { return x + y ;};

Typeinferens for parametre for generiske lambda-funktioner følger regler svarende til autotypeinferens for -variabler (men ikke helt identiske). Ovenstående kode svarer til følgende [11] :

struktur uden navn_lambda { skabelon < typenavn T , typenavn U > auto operator ()( T x , U y ) const { return x + y ;} }; auto lambda = unavngivet_lambda ();

Indfangning af udtryk for lambda-funktioner

C++11 lambda-funktioner giver dig mulighed for at fange variabler, der er erklæret i et ydre omfang ved at videregive efter reference eller værdi. Det betyder, at du ikke ved værdi kan fange variabler af typer, der kun kan flyttes (men ikke kopieres) [12] . C++14 giver dig mulighed for at fange variabler med vilkårlig udtryksinitialisering. Dette gør det muligt at fange variabler med værdibevægelse og at erklære variable med navne, der ikke er erklæret i højere omfang [7] .

Udtryk fanges ved hjælp af initialiseringsprogrammer:

auto lambda = [ værdi = 1 ] { returværdi ; };

Lambdafunktionen lambdareturnerer 1, fordi valueden passende initialisering er blevet udløst for parameteren. Typen af ​​den opfangede parameter udledes af initialiseringstypen, svarende til at erklære en variabel med specificatoren auto.

Denne funktion kan bruges til at fange med bevægelse ved hjælp af standardfunktionen std::move:

auto ptr = make_unique < int > ( 10 ); auto lambda = [ værdi = std :: move ( ptr )] { return * value ;};

Attribut [[deprecated]]

Attributten deprecatedgiver dig mulighed for at markere enheder som forældede. Disse entiteter kan stadig tilgås, men en kompileringsadvarsel udsendes. Argumentet deprecatedkan være en bogstavelig streng, der forklarer udfasningsårsagen og/eller mulig erstatning.

[[ forældet ]] intf ( ); [[ forældet ( "g() er ikke trådsikker. Brug h() i stedet for g()" )]] void g ( int & x ); void h ( int & x ); void test () { int a = f (); // advarsel: 'f' er forældet g ( a ); // advarsel: 'g' er forældet: g() er ikke trådsikker. Brug h() i stedet for g() }

Nye funktioner i standardbiblioteket

Delte mutexes og låse

C++14 tilføjer delte mutexes og en ny låsetype for delte mutexes [13] [14] .

Heterogen søgning i associative beholdere

C++ Standardbiblioteket definerer fire associative containerklasser. Disse klasser giver brugeren mulighed for at søge efter værdier baseret på en værdi af den type. Kortbeholdere giver brugeren mulighed for at angive en nøgle og en værdi, mens han søger på nøglen og returnerer værdien. Opslaget er dog altid blevet foretaget på en bestemt type nøgle, hvad enten det er nøglen, som i map, eller selve værdien, som i sæt.

C++14 tillader, at associative containere indekseres med en værdi af en vilkårlig type, forudsat at der er en overbelastet sammenligningsoperator, der kan sammenligne værdien af ​​den type med værdien af ​​containerens nøgletype [15] . Dette gør det muligt for kortbeholdere med en nøgletype at blive indekseret efter typeudtryk ved std::stringhjælp const char*af den overbelastede sammenligningsoperator operator<.

For at opretholde bagudkompatibilitet er heterogene opslag kun tilladt, hvis komparatoren, der sendes til den associative beholder, understøtter et sådant opslag. Standard biblioteksklasser std::less(standard for sæt- og kortbeholdere) og std::greatergiver mulighed for heterogene søgninger [16] .

Standard brugerdefinerede bogstaver

C++11 har en syntaks for brugerdefinerede bogstavelige suffikser, men ingen af ​​dem bruges i standardbiblioteket. C++14 tilføjer følgende standardliteraler [15] :

  • "s" for at skabe forskellige std::basic_stringtyper.
  • "h", "min", "s", "ms", "os" og "ns" for at oprette de tilsvarende tidsintervaller std::chrono::duration.
string str = "hej verden" s ; chrono :: varighed dur = 60 s ;

De to "s" literaler påvirker ikke hinanden, fordi strengen literal kun virker på strenge, mens den anden literal kun virker på tal [17] .

Adressering af tupler efter type

std::tuple, introduceret i C++11, giver dig mulighed for at aggregere flere indtastede værdier, der vil blive indekseret på kompileringstidspunktet. C++14 udvider funktionaliteten af ​​tuples for at tillade adgang til elementer i en tuple ikke kun efter indeks, men også efter type [15] . Hvis tuplen indeholder mere end ét element af den ønskede type, vil opslaget resultere i en kompileringsfejl [18] :

tuple < streng , streng , int > t ( "foo" , "bar" , 7 ); int i = < int > ( t ); // i == 7 int j = get < 2 > ( t ); // samme som før: j == 7 streng s = < streng > ( t ); // kompileringstidsfejl på grund af tvetydighed

Andre ændringer til standardbiblioteket

std::make_uniquekan bruges på samme måde som std::make_sharedtil objekter std::unique_ptr[7] .

For std::integral_constanttilføjet en overbelastning operator(), der returnerer en konstant værdi [15] .

Analogt med globale funktioner std::begin/std::ender der tilføjet funktioner, std::cbegin/std::cendder returnerer konstante iteratorer til begyndelsen og slutningen af ​​området.

Noter

  1. ISO/IEC 14882:2014 - Informationsteknologi - Programmeringssprog - C++ . ISO (14. januar 2014). Dato for adgang: 26. januar 2015. Arkiveret fra originalen 29. januar 2017.
  2. Udvalgsudkast, standard for programmeringssprog C++ (PDF). ISO (15. maj 2013). Hentet 24. juli 2014. Arkiveret fra originalen 21. januar 2022.
  3. Sutter, Herb (18. august 2014), Vi har C++14! , < https://isocpp.org/blog/2014/08/we-have-cpp14 > . Hentet 18. august 2014. Arkiveret 19. august 2014 på Wayback Machine 
  4. 1 2 3 4 5 Wong, Michael Udsigten fra C++ Standard-mødet april 2013 del 3 . C/C++ Cafe (30. april 2013). Hentet 14. juni 2013. Arkiveret fra originalen 13. oktober 2013.
  5. 1 2 3 Merrill, Jason N3638 Returtypefradrag for normale funktioner (revision 5) (17. april 2013). Hentet 14. juni 2013. Arkiveret fra originalen 25. august 2013.
  6. Smith, Richard N3652 Afslappende begrænsninger på constexpr-funktioner (18. april 2013). Hentet 24. juli 2014. Arkiveret fra originalen 25. august 2013.
  7. 1 2 3 4 Sutter, Emblem Trip Report: ISO C++ Forårsmøde 2013 . isocpp.org (20. april 2013). Hentet 14. juni 2013. Arkiveret fra originalen 20. august 2017.
  8. Dos Reis, Gabriel N3651 Variable skabeloner (revision 1) (PDF) (19. april 2013). Hentet 24. juli 2014. Arkiveret fra originalen 25. august 2013.
  9. Vandevoorde, Daveed; Voutilainen, Ville N3653 Medlemsinitialiserere og aggregater (17. april 2013). Hentet 24. juli 2014. Arkiveret fra originalen 25. august 2013.
  10. Crowl, Lawrence; Smith, Richard; Snyder, Jeff; Vandevoorde, Daveed N3781 Enkelt-anførselstegn som en ciffer-separator (25. september 2013). Hentet 15. oktober 2014. Arkiveret fra originalen 13. april 2014.
  11. Faisal, Vali; Sutter, Urt; Abrahams, Dave N3649 Generiske (polymorfe) lambdaudtryk (revision 3) (19. april 2013). Hentet 24. juli 2014. Arkiveret fra originalen 25. august 2013.
  12. Flyt fangst i Lambda . stak overløb . Hentet 24. juli 2014. Arkiveret fra originalen 24. januar 2013.
  13. Wong, Michael Udsigten fra C++ Standard-mødet, april 2013, del 3 . C/C++ Cafe (30. april 2013). Hentet 14. juni 2013. Arkiveret fra originalen 13. oktober 2013.
  14. Howard, Hinnant; Vollmann, Detlef; Boehm, Hans N3659 Fælles låsning i C++ (Revision 2) (19. april 2013). Hentet 24. juli 2014. Arkiveret fra originalen 19. august 2013.
  15. 1 2 3 4 Wong, Michael Udsigten fra C++ Standard-mødet, april 2013, del 2 . C/C++ Cafe (26. april 2013). Hentet 14. juni 2013. Arkiveret fra originalen 13. oktober 2013.
  16. N3657 Tilføjelse af heterogent sammenligningsopslag til associative beholdere (rev. 4) (19. marts 2013). Hentet 24. juli 2014. Arkiveret fra originalen 19. august 2013.
  17. Peter, Sommerlad N3642 Brugerdefinerede bogstaver til standardbibliotekstyper (del 1 - version 4) (PDF) (18. april 2013). Hentet 24. juli 2014. Arkiveret fra originalen 25. august 2013.
  18. Spertus, Mike N3670 Ordlyd til adressering af tuples efter type: Revision 2 (19. april 2013). Hentet 24. juli 2014. Arkiveret fra originalen 19. august 2013.