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 .
Dette afsnit introducerer nye kernesprogfunktioner i C++14.
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 }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] .
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] :
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.
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] .
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] .
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.
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 ;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 ();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 ;};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() }C++14 tilføjer delte mutexes og en ny låsetype for delte mutexes [13] [14] .
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] .
C++11 har en syntaks for brugerdefinerede bogstavelige suffikser, men ingen af dem bruges i standardbiblioteket. C++14 tilføjer følgende standardliteraler [15] :
De to "s" literaler påvirker ikke hinanden, fordi strengen literal kun virker på strenge, mens den anden literal kun virker på tal [17] .
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 = få < int > ( t ); // i == 7 int j = get < 2 > ( t ); // samme som før: j == 7 streng s = få < streng > ( t ); // kompileringstidsfejl på grund af tvetydighedstd::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.
C++ | |
---|---|
Ejendommeligheder | |
Nogle biblioteker | |
Kompilere | |
påvirket | |
|