A C++14 a C++ szabvány ISO/IEC JTC1 változatának nem hivatalos neve (teljes név: " International Standard ISO/IEC 14882:2014(E) Programming Language C++ ") [1] . A C++14 a C++11 kis kiterjesztésének tekinthető, amely többnyire hibajavításokat és kisebb fejlesztéseket tartalmaz. Az Új Szabványok Fejlesztési Bizottsága 2013. május 15-én tette közzé az N3690 tervezetet [2] . Az N3936 munkatervezet 2014. március 2-án jelent meg, a végső szavazási időszak 2014. augusztus 15-én zárult, az eredményhirdetés (egyhangú jóváhagyás) 2014. augusztus 18-án jelent meg [3] .
Mivel a szabvány fejlesztése hosszadalmas volt, és a végleges verzió kiadásának éve nem volt meghatározva, a fejlesztés során a "C++1y" elnevezést is használták, hasonlóan ahhoz, ahogy a C++11 szabványt "C+"-nak nevezték. +0x" a megjelenés előtt (ennek a verziónak a megjelenése 2010-ig volt várható).
Az alább leírt nyelvi jellemzők az N3797 munkatervezetnek felelnek meg . Ezekben apró eltérések lehetnek a szabvány végleges változatához képest .
Ez a rész a C++14 új alapvető nyelvi funkcióit mutatja be.
A C++11 lehetővé teszi, hogy egy kifejezés visszatérési típusából következtessen a lambda függvények visszatérési típusára. A C++14 ezt a képességet minden funkcióra kiterjeszti. return expression;Az új szabvány a lambda függvények típuskövetkeztetését is leírja, a [4] -től eltérő formában .
Az automatikus visszatérési típus-következtetés használatához egy függvényt úgy kell deklarálni, autohogy visszatérési típusa legyen, de a C++11 visszatérési típus farokspecifikátora nélkül:
auto DeduceReturnType (); // A visszatérési típus később kerül meghatározásra.Ha több kifejezést ad vissza a függvény törzsének különböző helyein, akkor ezeknek a kifejezéseknek közös kikövetkeztetett típussal kell rendelkezniük [5] .
A return típusú automatikus következtetést használó függvények használhatják a továbbítási deklarációt, de csak definiálásuk után használhatók. Ezeknek a meghatározásoknak ugyanabban a fordítási egységben kell rendelkezésre állniuk, amelyben használják őket.
Lehetséges ilyen függvényekben rekurziót használni , de a rekurzív hívást legalább egy visszatérési érték után kell végrehajtani ebben a függvényben [5] :
automatikus javítás ( int i ) { ha ( i == 1 ) vissza i ; // int visszatérési típusként jelenik meg else return Helyes ( i -1 ) + i ; // most már hívhatod } autoWrong ( int i ) { _ ha ( i != 1 ) return Rossz ( i -1 ) + i ; // nem megfelelő hely a rekurzióhoz. Nincs előzetes visszaküldés. más vissza i ; // az int visszatérési típusként jelenik meg }A C++11 két módszert adott a típusok megállapítására. autolehetővé tette változók létrehozását egy hozzárendelt kifejezésen alapuló típussal. decltypelehetővé tette egy tetszőleges kifejezés eredő típusának meghatározását. Az általuk kikövetkeztetett típusok azonban eltértek egymástól decltype. autoKonkrétan autoa nem hivatkozási típusra mindig úgy következtet, mintha feldolgozva lenne std::remove_reference, míg auto&&mindig egy referenciatípusra következtet. Az eredmény decltypeazonban lehet referencia típusú vagy nem referencia típusú, a feldolgozott kifejezéstől függően [4] :
int i ; int && f (); auto x3a = 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&&A C++14 hozzáadta a szintaxist decltype(auto). decltypeEz a szintaxis lehetővé teszi a deklarációs szabályok használatát auto. Ennek csak a kazánkódban van értelme.
A szintaxis decltype(auto)használható visszatérési típusok megállapítására is, ha a függvény visszatérési típusát adjuk meg a hely decltype(auto)helyett [5] . auto
A C++11 bevezeti a constexpr-functions fogalmát: a fordítási időben végrehajtható függvényeket. Az általuk visszaadott értékek olyan műveletekben használhatók, amelyek állandó kifejezést igényelnek, például sablon argumentumként. A C++11 -ben azonban a constexpr-függvények csak egy visszatérési kifejezést tartalmazhatnak (valamint static_asserttöbb más deklarációt is).
A C++14 nyelvben ezek a korlátozások részben megszűnnek. constexpr-függvények mostantól a következő elemeket tartalmazhatják [4] :
Az utasítás gotonem megengedett a constexprC++14 -függvényben.
A nem -funkciók hívására vonatkozó korlátozások constexprérvényben maradnak. Így, ha fortartományokhoz használjuk, a függvényeket beginés a endkonténereket túl kell terhelni constexpr-ként. Beépített típus std::initializer_listesetén a függvények constexprként vannak begin/enddefiniálva lokálisan és globálisan is.
Ezenkívül a C++11-ben minden nem statikus metódus, amely -vel deklarált, constexprimplicit módon const-függvényként lett kezelve a függvényhez képest this. Ez a korlátozás megszűnt; A nem statikus metódusok most már nem const[6] . Azonban, mint korábban említettük, egy nem const constexpr-metódus csak akkor tudja megváltoztatni az osztálymezőket, ha az objektum élettartama egy konstans kifejezés kiértékelése során kezdődött.
A C++ korábbi verzióiban a sablonozás függvényekre és osztályokra korlátozódott. A C++14 lehetővé teszi sablonváltozók létrehozását.
sablon < típusnévT > _ constexpr T pi = T ( 3,1415926535897932385 ); // A szokásos szakosodási szabályok érvényesek: sablon <> constexpr const char * pi < const char *> = "pi" ;Ebben a példában egy változósablon van definiálva pi, amelyhez hozzá lehet férni a pi értékének különböző típusokhoz való lekéréséhez (például 3egy egész típus olvasásakor; a legközelebbi érték a float, doublevagy long doubleamikor a , illetve a , illetve a olvasása floatsorán doublestb long double.).
Az ilyen deklarációk és meghatározások magukban foglalják a szokásos sablonszabályokat, beleértve a specializációs szabályokat [7] [8] .
A C++11 bevezette az osztálymező-inicializálókat, amelyek olyan kifejezések, amelyek osztályszintű mezőkre vonatkoznak, ha a konstruktor nem inicializálja azokat önállóan. Az aggregátumok definíciója megváltozott, hogy kifejezetten kizárja az összes taginicializálóval rendelkező osztályt, így az összesített inicializálás nem volt lehetséges számukra.
A C++14 eltávolítja ezt a korlátozást [4] , és lehetővé teszi az osztályok összesített inicializálását mezőinicializálókkal. Ha a kapcsos zárójelben lévő inicializálók listája nem ad értéket ehhez az argumentumhoz, akkor a mező inicializálója [9] átveszi az irányítást .
A C++14 numerikus literáljai bináris formában adhatók meg [4] . A szintaxis a 0bvagy előtagokat használja 0B. Hasonló szintaxis használatos a Java , Python , Perl és D nyelvekben is .
A C++14-ben az aposztrófot használhatjuk a bitek tetszőleges elválasztására numerikus literálokban [10] . Egyes esetekben ez leegyszerűsíti a nagy numerikus állandók észlelését a kódban, és javítja a kód olvashatóságát.
auto integer_literal = 1'000'000 ; auto floating_point_literal = 0,000'015'3 ; auto binary_literal = 0b0100'1100'0110 ; auto silly_example = 1'0'0'000'00 ;A C++11-ben a lambda függvény paramétereit meghatározott típusokkal kellett deklarálni. A C++14 megszünteti ezt a korlátozást, és lehetővé teszi a lambda függvény paramétereinek deklarálását egy típusspecifikátorral auto[7] .
auto lambda = []( auto x , auto y ) { return x + y ;};Az általános lambda-függvények paramétereinek típuskövetkeztetése hasonló szabályokat követ, mint a auto-változók típuskövetkeztetése (de nem teljesen azonos). A fenti kód egyenértékű a következővel [11] :
struct unnamed_lambda { sablon < típusnév T , típusnév U > auto operátor ()( T x , U y ) const { return x + y ;} }; auto lambda = unnamed_lambda ();A C++11 lambda függvények lehetővé teszik a külső hatókörben deklarált változók rögzítését referencia vagy érték szerinti átadással. Ez azt jelenti, hogy nem lehet érték szerint rögzíteni olyan típusú változókat, amelyek csak áthelyezhetők (de nem másolhatók) [12] . A C++14 lehetővé teszi változók rögzítését tetszőleges kifejezés inicializálással. Ez lehetővé teszi a változók értékmozgással történő rögzítését és a magasabb hatókörben nem deklarált nevű változók deklarálását [7] .
A kifejezések rögzítése inicializálók segítségével történik:
auto lambda = [ érték = 1 ] { visszatérési érték ;};A lambda függvény lambda1-et ad vissza, mert valuea megfelelő inicializáló aktiválódott a paraméterhez. A rögzített paraméter típusára az inicializátor típusából következtet a rendszer, hasonlóan ahhoz, mintha egy változót a specifikátorral deklarálnánk auto.
Ez a funkció használható mozgás közbeni rögzítésre a szabványos funkció használatával std::move:
auto ptr = make_unique < int > ( 10 ); auto lambda = [ érték = std :: move ( ptr )] { return * érték ;};Az attribútum deprecatedlehetővé teszi az entitások elavultként való megjelölését. Ezek az entitások továbbra is elérhetők, de fordítási időre figyelmeztet a rendszer. Az argumentum deprecatedlehet egy karakterlánc , amely megmagyarázza az elavulás okát és/vagy a lehetséges cserét.
[[ elavult ]] intf ( ); [[ elavult ( "g() nem szálbiztos. Használja a h()-t a g() helyett" )]] void g ( int & x ); void h ( int & x ); érvénytelen teszt () { int a = f (); // figyelmeztetés: 'f' elavult g ( a ); // figyelmeztetés: 'g' elavult: g() nem szálbiztos. Használja a h()-t g() helyett }A C++14 megosztott mutexet és új zártípust ad hozzá [13] [14] .
A C++ Standard Library négy asszociatív tárolóosztályt határoz meg. Ezek az osztályok lehetővé teszik a felhasználó számára, hogy az adott típusú értékek alapján keressen értékeket. A térképtárolók lehetővé teszik a felhasználó számára, hogy kulcsot és értéket adjon meg, miközben keres a kulcson, és visszaadja az értéket. A keresés azonban mindig egy bizonyos típusú kulcson történt, legyen az a kulcs, mint a térképen, vagy maga az érték, mint a készletben.
A C++14 lehetővé teszi az asszociatív konténerek tetszőleges típusú értékkel történő indexelését, feltéve, hogy van egy túlterhelt összehasonlító operátor, amely össze tudja hasonlítani az adott típus értékét a tároló kulcstípusának értékével [15] . Ez lehetővé teszi a kulcstípussal rendelkező leképezési tárolók típuskifejezések szerinti indexelését std::stringa const char*túlterhelt összehasonlító operátor használatával operator<.
A visszamenőleges kompatibilitás fenntartása érdekében a heterogén keresések csak akkor engedélyezettek, ha az asszociatív tárolónak átadott összehasonlító támogatja az ilyen keresést. Szabványos könyvtárosztályok std::less(alapértelmezett a halmaz- és leképezési konténereknél), és std::greaterlehetővé teszik a heterogén kereséseket [16] .
A C++11-nek van szintaxisa a felhasználó által definiált literális utótagokhoz, de egyiket sem használják a szabványos könyvtárban. A C++14 a következő szabványos literálokat adja hozzá [15] :
A két "s" literál nem hat egymásra, mert a string literál csak karakterláncokon működik, míg a második literál csak számokon [17] .
std::tupleA C++11-ben bevezetett, több beírt érték összesítését teszi lehetővé, amelyeket a fordításkor indexelünk. A C++14 kibővíti a sorok funkcionalitását, hogy lehetővé tegye a tuple elemeinek elérését nem csak index, hanem típus szerint is [15] . Ha a tuple egynél több elemet tartalmaz a kért típusból, a keresés fordítási idejű hibát eredményez [18] :
tuple < string , string , int > t ( " foo " , " bar " , 7 ); int i = get < int > ( t ); // i == 7 int j = get < 2 > ( t ); // ugyanaz, mint korábban: j == 7 string s = get < string > ( t ); // fordítási idő hiba a kétértelműség miattstd::make_uniqueugyanúgy használható, mint std::make_sharedaz objektumoknál std::unique_ptr[7] .
Túlterhelés std::integral_constanthozzáadásához operator(), amely állandó értéket ad vissza [15] .
A globális függvényekkel analóg módon olyan függvényeket std::begin/std::endadtunk hozzá std::cbegin/std::cend, amelyek az állandó iterátorokat a tartomány elejére és végére adják vissza.
C++ | |
---|---|
Sajátosságok | |
Néhány könyvtár | |
Fordítók | |
befolyásolta | |
|