A C++17 (más néven C++1z) a C++ szabvány ISO /IEC verziójának neve. A C++17 specifikációit 2017 decemberében tették közzé [1] [2] .
A konstans értéke a __cpluspluslett 201703L, ezt használjuk a feltételes fordításhoz .
A trigráfokat nem szabványos kódolású és/vagy korlátozott billentyűzettel rendelkező gépeknél használták. A 80-as évek végén, a 8 bites kódolások és az olcsó gumimembrán billentyűzetek elterjedésével a trigráfok tulajdonképpen értelmüket vesztették, harminc évvel később pedig természetesen kizárták [3] [4] .
// A következő sor végrehajtásra kerül??????????????????/ a ++ ; /* trigráfokkal ez a sor megjegyzésre kerül - trigráf ??/ egyenértékű a következővel: \ */A C nyelv "hordozható assembler" volt: lehetővé tette gyors, különböző számítógépeken lefordító programok készítését, emellett assembler segédprogramokat ( linker , librarian) is használt. Az olyan fogalmak, mint a „ fejlécfájl ” és a „ fordítási egység ” ezeknek az időknek a visszhangja.
A szó registereredetileg a program kézi optimalizálásához kapcsolódott. A modern fordítók „a motorháztető alatt” rengeteg optimalizálást hajtanak végre, és az ilyen kézi vezérlés feleslegesnek tűnik. A C++11-ben a szót nemkívánatosnak nyilvánították. A szó továbbra is fenntartva van, és egy nap más célra is felhasználható – mint például a C++11-ben [5] . auto
A művelet nyilvánvalóan nem biztonságos, és tiltott a C++98-ban [6] . A művelet --hiányzik.
A bejelentett kivételek void f() throw(A, B, C);, amelyek például a Java -ban találhatók, többet ártanak, mint használnak. C++11-ben kitiltották, C++17-ben eltávolították. A [7]throw() szinonimája maradt . noexcept(true)
Köztük std::auto_ptrrégi std::random_shufflefunkcionális adapterek [8] [9] .
Ehelyett a unique_ptr, és a / shufflefüggvényen alapuló új függvénysablonok használatosak . Azt állítják, hogy bármely kód mechanikusan konvertálható -ra , egy egyszerű kiegészítéssel, ha a tulajdonjog átruházására kerül sor. functionbindauto_ptrunique_ptrstd::move
A C++98-ban [10]iostream tiltott különálló részeket is eltávolították .
Összesen öt túlterhelés, beleértve ezt az egyet is
sablon < classAlloc > _ function ( std :: allocator_arg_t , const Alloc & alloc ) noexcept ;Az érthetetlen szemantika és megvalósítási nehézségek miatt előzetes tiltás nélkül eltávolították [11] .
A standard könyvtár számos ritka funkciója tiltott: [12] [13] [14]
Azt ígérik, hogy teljesen eltávolítják őket C++20-ban.
A C11-re való átállással a fejlécek <ccomplex>, <cstdalign>, <cstdbool>, <ctgmath>. A fájl <ciso646>nem tiltott [19] .
A C++11-hez hozzáadott univerzális inicializátor int x{};lehetővé teszi objektumok, struktúrák, tömbök létrehozását egyetlen szintaxissal. A C++17-ben tisztázva van: ha típus helyett áll , akkor a autofelhasználó egy objektumot szeretne létrehozni, és nincs szükség inicializáló_listára.
Ugyanakkor auto x = {1, 2, 3};folytatja a létrehozást: egyrészt a kompatibilitás érdekében , másrészt for (auto x : {1, 2, 3})egy objektumhoz auto x = 1;[20] [9] tartozik .
auto x1 = { 3 }; // std::initializer_list<int> auto x2 { 1 , 2 }; // hiba most auto x3 { 3 }; // intA és függvények mostantól különböző típusú függvények (de nem alkothatnak túlterhelt halmazt). Ez lehetővé teszi, hogy az API visszahívásokat kérjen , amelyek nem dobnak kivételeket, valamint optimalizálja a kódot egyikre sem [21] . void f() noexcept(true);void f() noexcept(false);
A C++11 bevezette az elméletinél nagyobb illesztésű adatstruktúrák létrehozásának lehetőségét. Ezt a lehetőséget felvette az új művelet [22] .
osztály alignas ( 16 ) float4 { float f [ 4 ]; }; float4 * p = új float4 [ 1000 ];Az új operátor túlterhelt egy további paraméterrel, amely a túligazított objektum helyes kiosztását szolgálta a memóriában.
A prvalue fogalom jelentése megváltozott: most már csak inicializálás.
Bár a kódhoz SomeType a = 10;továbbra is szükség van a konstruktorra és az = operátorra, garantáltan csak a konstruktort hívják meg.
Ez azt jelenti, hogy a függvények olyan típusokat adhatnak vissza, amelyeket nem lehet másolni és áthelyezni.
Most a a.b, a->b, a->*b, a(b1, b2, b3), b += a(és más műveletek analógjai), a[b], a << bés műveletek a >> ba → b sorrendben kerülnek kiértékelésre a mellékhatások ellenőrzése érdekében [23] .
Ha függvényként hívjuk meg őket (például operator += (a, b)), a sorrend definiálatlan marad.
Vannak olyan sablonok, amelyek elfogadnak egy állandót.
template < int N > struct Tömb { int a [ N ]; };Mi lehet konstans N, és mi nem - ellenkezőleg. A sablonban lévő konstans nem lehet mutató mezőre, ideiglenes objektumra, karakterlánc-literálra, eredményre typeidvagy szabványos változóra __func__[17] [24] ;
A most for (auto v : x)azt jelenti , hogy lehetővé teszi a különböző típusok kezdetét és végét. auto __begin = begin-expr; auto __end = end-expr;
Ez az alapja a tartományokon keresztüli iterációnak, ami egy folyamatban lévő munka [25] .
Az std::vector és std::string tömbök a memória összefüggő régióival foglalkoznak. Bevezették a "folyamatos iterátor" [26] [27] fogalmát . Elvileg semmi sem változott.
Definíciókat is adtak más fogalmakhoz – továbbítási hivatkozás , alapértelmezett taginicializáló , sablonos entitás . Ez a munka a C++20 koncepciókon .
Korábban ezt a viselkedést implementáció határozta meg.
Ezzel egy időben készítettek "UTF-8 karaktereket", amelyek típusa van, és 0-tól 127-ig terjedő kódokat tartalmazhat, hasonlóan az UTF-8 karakterláncokhoz - úgy tűnik, hogy a program kevésbé függ a számítógépen lévő területi beállításoktól [ 17] [28] . char
A nem megfelelő szemantika miatt a „fogyaszt” rendelési módot verbálisan (jel nélkül ) betiltották, az „acquire” módszer alkalmazását szorgalmazva. Az új szemantikával kapcsolatos munka még folyamatban van, és talán egyszer feloldják a tilalmat [29] . [[deprecated]]
Mindenesetre a PowerPC -n és az ARM -en minden letöltés automatikusan elfogy , de nem mindegyik szerzi be , és a fogyasztási módszer többplatformos kódban mentheti az órákat [30] .
Ha static_assertnem működik, nem mindig szükséges elmondani a programozónak, hogy mi a baj - gyakran ő maga is kitalálja a szövegkörnyezetből. [31] .
static_assert ( sizeof ( wchar_t ) == 2 );Most már írhat a fejlécfájlba, és amikor ezt a fájlt tartalmazza a cpp fájlokban, akkor mindegyik ugyanarra az objektumra fog hivatkozni (az osztálykonstruktort nem hívják meg ismételten minden cpp fájlnál, ellentétben a vagy -vel ), inline const ClassName INSTANCE_NAMEconst ClassName INSTANCE_NAMEstatic const ClassName INSTANCE_NAME
A C++ nyelv hibája: sablonokban typenameés classhelyenként nem cserélhető [33] .
template < template < typename > class X > struct C ; // OK template < template < typename > typename X > struct D ; // nem fordítMindkét kulcsszó kifejezetten felcserélhetőnek van nyilvánítva.
Megjelent az összetett objektumok kicsomagolásához szükséges változók deklarálásának új módja, az úgynevezett strukturális kötés [34] .
auto [ hely , wasInserted ] = someMap . emplace ( kulcs , érték );Párokhoz, sorokhoz és más típusokhoz működik, ahol . std::get
Beágyazott névterek meghatározása: [9] [35] namespace A::B {} a namespace A { namespace B {} };
Például:
enum class TriBool { NEM , talán , IGEN , NN [[ Maybe_unused ]], NEM MEGHATÁROZOTT [[ elavult ( "Átnevezve erre: MAYBE" )]] = MAYBE }; constexpr int TriBool_N = static_cast < int > ( TriBool :: NN ); const char * triBoolNames [ TriBool_N ] = { "nem" , "talán" , "igen" };Még nincs deklarált cél [17] [36] , de ez lehetővé teszi a fordítóprogramok fejlesztői számára, hogy előálljanak egy - például deklarálják, hogy az NN elem speciális, és nem kell változókhoz hozzárendelni, feldolgozása -ben switch.
A SFINAE koncepció lehetővé tette egy olyan egyszerű sablon készítését enable_if, amely különböző funkcionalitást biztosít a különböző típusokhoz, de nehéz kódot ad. C++17-ben leegyszerűsíthetjük a programot: az operátor if constexpr(expression)példányosítja a kódot, ha a zárójelben lévő kifejezés igaz [37] .
sablon < classT > _ constexpr T abszolút ( T arg ) { return arg < 0 ? - arg : arg ; } sablon < classT > _ constexpr auto precision_threshold = T ( 0,000001 ); sablon < classT > _ constexpr bool close_enough ( T a , T b ) { if constexpr ( is_lebegő_pont_v < T > ) // << !! visszatér abszolút ( a - b ) < pontossági_küszöb < T > ; más return a == b ; }Ebben az esetben ügyelünk arra, hogy a törtszámok közötti különbség kicsi legyen, és az egész számokat egyszerűen ellenőrizzük az egyenlőség szempontjából.
Csomagolt kifejezések [17] [38] :
sablon < típusnév ... As > bool foo ( As ... args ) { return ( args && ...); }Hexadecimális mantissza és decimális kitevő: 0xC.68p+2, 0x1.P-126, hasonló a helyettesítéshez %a. A C a 99-es verzió óta támogatja ezt a szintaxist [39] .
Hasonlóan a helyi változók inicializálásához a -ban for, kompaktabbá teszi a kódot [40] .
if ( auto it = m . find ( key ); it != m . end ()) return it -> second ;Lehetővé teszi bármilyen típusú sablon paraméter beállítását a [41] segítségével . auto
template < auto X > struct B { static constexpr auto value = X ; }; B < 5 > b1 ; // OK: a sablonparaméter típusa int B < 'a' > b2 ; // OK: a sablonparaméter típusa char B < 2.5 > b3 ; // hiba: a sablon paraméter típusa nem lehet duplaVolt: . Ez lett: [42] . [self = *this]{ self.f(); }[*this]{ f(); }
enum classnéha arra használnak, hogy egy másik, semmivel nem kompatibilis egész számtípust készítsenek. Mostantól az ilyen típusú változók inicializálhatók számokkal [43]
enum class Handle : intptr_t { INVALID = 0 }; Fogantyú h { 42 }; Fogantyú h = 42 ; // tilosGyakran előfordul, hogy változatlan karakterláncot kell átadnia egy másik kódrészletnek, ezt a következő módszerekkel teheti meg:
void doSmth ( const char * s ); // mi van, ha null karakter van a sztringben? Igen, és a függvény belseje hibás lesz void doSmth ( const std :: string & s ); // mi van, ha a karakterlánc nem karakterlánc, és memóriát kell lefoglalnunk?A C++17 bevezetett egy típust – egy string_view karakterláncot, amelynek csak egy mutatója és egy hossza van, nincs tulajdonjog, nincs memóriakezelés, és nincs még nulla lezáró sem –, így nincs benne c_str(). Csak a szegélyek (eleje/hossz) módosíthatók, a karakterek nem. A programozó feladata, hogy megbizonyosodjon arról, hogy az objektum ne élje túl azt a memóriapuffert, ahol a karakterlánc található, és a paraméterek átadása remekül használható. Az objektum string_viewnagyon kicsi (2 bites gép), és nem hivatkozással, hanem értékkel kell átadni.
string_viewmaga egy absztrakció - elvonatkoztatja a karakterlánc tárolási módszert, egyetlen dolgot igényel - hogy a szöveges adatok egymást követő bájtok legyenek a memóriában. Csak összetett szokatlan szerkezetek (például heveder/kötél ) tárolnak véletlenszerű karakterláncokat. És az összes többi - és , és , és különféle tömbök - konvertálva . stringconst char*string_view
Két új állandó van, hardware_constructive_interference_sizeés hardware_destructive_interference_size. Így a felhasználó elkerülheti a hamis megosztást (destruktív interferencia) és javíthatja a lokalitást (konstruktív interferencia).
struct keep_apart { alignas ( hardware_desstructive_interference_size ) atomic < int > cat ; alignas ( hardware_desstructive_interference_size ) atomic < int > dog ; // a macska távol áll a kutyától, különböző szálakból változtathatók. }; struct -together { atomi < int > kutya ; int kölyökkutya ; }; struct kennel { //... alignas ( sizeof ( együtt )) together pack ; //... }; static_assert ( sizeof ( együtt ) <= hardver_konstruktív_interferencia_méret ); // győződjön meg arról, hogy együtt egy gyorsítótár sor.Elméletileg mindkét konstansnak azonosnak kell lennie, de a heterogén architektúrák támogatása érdekében úgy döntöttek, hogy két állandót készítenek. [ötven]
Mutex, amely lehetővé teszi a párhuzamos olvasást és írást egy [51] . Az erre szolgáló blokkolókat shared_lockés unique_lock.
A könyvtárban megjelentek a függvények, az úgynevezett levonási útmutatók , amelyek lehetővé teszik ezt:
std :: p pár ( 2 , 4,5 ); // egy std :: vektor < int > v = { 1 , 2 , 3 , 4 }; std :: vektor x ( v.begin ( ), v.end ( ) ) ; 2A std::mapés std::unordered_mapkét új funkcióval bővült [52] .
#include <iostream> #include <térkép> osztály pár { nyilvános : int érték1 , érték2 ; Pár () : érték1 ( 0 ), érték2 ( 0 ) {} explicit pár ( int aÉrték1 ) : érték1 ( aÉrték1 ), érték2 ( 0 ) {} Pár ( int aValue1 , int aValue2 ) : érték1 ( aÉrték1 ), érték2 ( aÉrték2 ) {} }; int main () { std :: térkép < std :: string , Pair > m ; // C++11 m [ "a" ] = Pár ( 3 , 4 ); m . emplace ( "a" , 1 ); // A pár mindig létrejön // C++17 m . insert_or_assign ( "a" , Pár ( 3 , 4 )); m . try_emplace ( "a" , 1 ); // A pár létrejön, amikor szükséges return 0 ; }Nem szabványos matematikai függvények kerültek be az std névtérbe: beta, , , , , , , , , , , [53] [54] . Nincsenek std-n kívül (in ). cyl_bessel_i/j/kcyl_neumann[comp_]ellint_1/2/3expinthermite[assoc_]laguerre[assoc_]legendreriemann_zetasph_besselsph_legendresph_neumannmath.h
Az első mondattól (2010): "Reméljük, hogy ennek a javaslatnak az elfogadása azt az üzenetet küldi a különböző számítástechnikai közösségeknek, hogy a közhiedelem ellenére a C++ az ő iparágukban is megfelelő." Aztán nem fogadták el. Most már a nagy könyvtárszállítók ( Dinkumware , Boost , GCC ) már rendelkeznek ezekkel a funkciókkal.
Szintén hozzáadva a GCD [55] és az LCM [56] számítását , a tartományba való redukció függvényét ( ) [57] , háromdimenziós hipotenúzát . clamphypot(x, y, z)
A következőre épülő fájlrendszer-könyvtár boost::filesystemlehetővé teszi: [58]
Volt egy osztály , amely bármilyen típusú adatot tartalmazhatott [59] [60] . Megvalósításokra van szükség ahhoz, hogy kis objektumokat memória lefoglalása nélkül illesszen be. A függvény a típus pontos egyezését igényli, és nem ad semmit, ha a . std::anyanyany_castany_cast<double>int
std :: cout << std :: boolalpha ; std :: bármely a = 1 ; std :: cout << a . típus (). név () << ": " << std :: any_cast < int > ( a ) << std :: endl ; a = 3,14 ; std :: cout << a . típus (). név () << ": " << std :: any_cast < double > ( a ) << std :: endl ; a = igaz ; std :: cout << a . típus (). név () << ": " << std :: any_cast < bool > ( a ) << std :: endl ; // i: 1 // d: 3,14 // b: igazVannak egyszerűbb std::variant<int, bool, double>és std::optional<T>.
A C++ ismert hátránya: a számok alacsony szintű szöveggé konvertálásához memóriafoglalás nélkül nehéz és megbízhatatlant kell futtatni sprintf, és a szöveg C-vel hagyott számmá történő beépített konvertálása meglehetősen megbízhatatlan.
Jelenleg beépített helyi-független szupersebesség from_chars[61] és to_chars[62] . Úgy vannak megtervezve, hogy nem igényelnek (és nem állítanak elő) záró nullát, és működhetnek pl string_view. Korlátozásuk és helyi függetlenségük miatt elsősorban JSON -hoz és XML -hez készültek , ahol óriási sebességre van szükség.
Az STL adatstruktúrák ( karakterláncok , vektorok stb.) tartalmaznak egy sablonparamétert - egy memórialeosztót. Ez az allokátor általános programozási koncepcióként működik , nem objektum-orientált interfészként: a halomban és a készletben lévő memória lefoglalása különböző inkompatibilis típusokat eredményez. Az osztály egy ritka feladat szokásos kezdete: bizonyos feltételektől függően foglaljon le memóriát a kupacban vagy a készletben. polymorphic_allocator
Önmagában nem interfész, de egy interfészhez van társítva . polymorphic_allocatormemory_resource
Lehetővé teszi a függvények, objektumok () operátorral ( functors ) és lambda objektumok következetes hívását [63] . Szintén hozzáadott funkciók , , . is_invocableis_invocable_rinvoke_result
69 algoritmushoz , és párhuzamos változatokat találtak ki [64] [65] [66] . <algorithm><numeric><memory>
C programozási nyelv | |
---|---|
Fordítók |
|
Könyvtárak | |
Sajátosságok | |
Néhány leszármazott | |
C és más nyelvek |
|
Kategória:C programozási nyelv |
C++ | |
---|---|
Sajátosságok | |
Néhány könyvtár | |
Fordítók | |
befolyásolta | |
|