C++11

Kokeneet kirjoittajat eivät ole vielä tarkistaneet sivun nykyistä versiota, ja se voi poiketa merkittävästi 15.9.2020 tarkistetusta versiosta . tarkastukset vaativat 24 muokkausta .

C++11 [1] [2] tai ISO/IEC 14882:2011 [3] (standardia kehitettäessä sen koodinimi oli C++0x [4] [5] ) – uusi versio C++ -kielistandardi aiemmin voimassa olevan ISO /IEC 14882:2003:n sijaan . Uusi standardi sisältää lisäyksiä kielen ytimeen ja laajennuksen standardikirjastoon, mukaan lukien suurin osa TR1 :stä  - paitsi ehkä erityisten matemaattisten funktioiden kirjasto. Standardien uudet versiot sekä eräät muut C++-standardointiasiakirjat julkaistaan ​​ISO C++ -komitean verkkosivustolla [6] . C++ ohjelmointiesimerkkejä

Ohjelmointikielten kykyjä kehitetään asteittain (tällä hetkellä C++11:n jälkeen on julkaistu seuraavat vakiolaajennukset: C++14, C++17, C++20). Tämä prosessi aiheuttaa väistämättä yhteensopivuusongelmia olemassa olevan koodin kanssa. Kansainvälisen standardin N3290 lopullisen luonnoksen liitteessä C.2 [diff.cpp03] kuvataan joitakin C++11:n ja C++03 :n  välisiä ristiriitoja.

Ehdotetut muutokset standardiin

Kuten jo mainittiin, muutokset vaikuttavat sekä C++ -ytimeen että sen vakiokirjastoon.

Tulevan standardin kutakin osaa kehittäessään komitea käytti useita sääntöjä:

Huomiota kiinnitetään aloittelijoihin, jotka muodostavat aina suurimman osan ohjelmoijista. Monet aloittelijat eivät pyri syventämään C ++ -taitojaan, vaan rajoittuvat käyttämään sitä tehdessään kapeita erityistehtäviä [7] . Lisäksi, kun otetaan huomioon C++:n monipuolisuus ja sen käyttömahdollisuudet (mukaan lukien sekä erilaiset sovellukset että ohjelmointityylit), ammattilaisetkin voivat löytää itselleen uusia ohjelmointiparadigmoja .

Ydinkielen laajentaminen

Toimikunnan ensisijaisena tehtävänä on kehittää C++-kielen ydin. Ydintä on parannettu merkittävästi, monisäikeinen tuki on lisätty, yleisohjelmoinnin tukea on parannettu , alustus on yhtenäistetty ja sen suorituskyvyn parantamiseksi on tehty työtä.

Mukavuuden vuoksi ytimen ominaisuudet ja muutokset on jaettu kolmeen pääosaan: suorituskyvyn parannukset, käyttömukavuuden parannukset ja uudet toiminnot. Yksittäiset elementit voivat kuulua useisiin ryhmiin, mutta niitä kuvataan vain yhdessä - sopivimmassa.

Suorituskyvyn parantaminen

Nämä kielikomponentit otetaan käyttöön muistin vähentämiseksi tai suorituskyvyn parantamiseksi.

Väliaikaiset objektiviittaukset ja siirtosemantiikka

C++-standardin mukaan väliaikainen olio , joka syntyy lausekkeen arvioinnista, voidaan välittää funktioille, mutta vain vakioviittauksella ( const & ). Funktio ei pysty määrittämään, voidaanko ohitettua objektia pitää väliaikaisena ja muokattavana (const-objektia, joka voidaan myös välittää tällaisella viittauksella, ei voida muokata (laillisesti)). Tämä ei ole ongelma yksinkertaisissa rakenteissa, kuten complex, mutta monimutkaisissa tyypeissä, jotka vaativat muistin varausta ja purkamista, väliaikaisen objektin tuhoaminen ja pysyvän luominen voi olla aikaa vievää, kun taas osoittimia voi yksinkertaisesti välittää suoraan.

C++11 esittelee uudentyyppisen viittauksen , rvalue - viittauksen .  Sen ilmoitus on: type && . Uudet ylikuormitusresoluutiosäännöt mahdollistavat erilaisten ylikuormitettujen funktioiden käyttämisen ei-const-väliaikaisille objekteille, jotka on merkitty rarvoilla, ja kaikille muille objekteille. Tämä innovaatio mahdollistaa niin kutsutun liikkuvan semantiikan toteuttamisen .

Esimerkiksi std::vector on yksinkertainen kääre C-taulukon ympärille ja muuttuja, joka tallentaa sen koon. Kopiointikonstruktori std::vector::vector(const vector &x)luo uuden taulukon ja kopioi tiedot; siirtokonstruktori std::vector::vector(vector &&x)voi yksinkertaisesti vaihtaa pituuden sisältäviä osoittimia ja muuttujia.

Mainosesimerkki.

malli < luokka T > luokkavektori _ { vektori ( const vektori & ); // Kopioi konstruktori (hidas) vektori ( vektori && ); // Konstruktorin siirto väliaikaisesta objektista (nopea) vektori & operaattori = ( const vektori & ); // Säännöllinen osoitus (hidas) vektori & operaattori = ( vektori && ); // Siirrä väliaikainen objekti (nopea) void foo () & ; // Funktio, joka toimii vain nimetylle objektille (hidas) void foo () && ; // Toiminto, joka toimii vain väliaikaiselle objektille (nopea) };

Väliaikaisiin linkkeihin liittyy useita malleja, joista kaksi tärkeintä ovat ja . Ensimmäinen tekee tavallisesta nimetystä objektista väliaikaisen viittauksen: moveforward

// std::siirrä malliesimerkki void bar ( std :: string && x ) { staattinen std :: stringsomeString ; _ someString = std :: siirrä ( x ); // x=string&-funktion sisällä, joten toinen siirto siirtotehtävän kutsumiseksi } std :: stringy ; _ bar ( std :: siirrä ( y )); // ensimmäinen siirto muuttaa merkkijonon& merkkijonoksi&& kutsupalkkiin

Mallia käytetään vain metaohjelmoinnissa, se vaatii eksplisiittisen malliparametrin (sillä on kaksi erottamatonta ylikuormitusta) ja se liittyy kahteen uuteen C++-mekanismiin. Ensimmäinen on linkkien liimaus: , sitten . Toiseksi yllä oleva bar()-funktio vaatii väliaikaisen objektin ulkopuolella, mutta sisäpuolella x-parametri on tavallinen nimetty (lvalue) varalle, mikä tekee mahdottomaksi erottaa automaattisesti string&-parametria merkkijono&&-parametrista. Tavallisessa ei-mallifunktiossa ohjelmoija voi laittaa tai jättää liikkumatta, mutta entä malli? forwardusing One=int&&; using Two=One&;Two=int&

// esimerkki mallin käytöstä std::forward class Obj { std :: stringfield ; _ malli < luokkaT > _ Obj ( T && x ) : kenttä ( std :: eteenpäin < T > ( x )) {} };

Tämä konstruktori kattaa tavalliset (T=string&), kopiointi (T=const string&) ja siirto (T=string) ylikuormitukset referenssiliimauksella. Ja eteenpäin ei tee mitään tai laajenee muotoon std::move riippuen T:n tyypistä, ja rakentaja kopioi, jos se on kopio, ja siirtää, jos se on siirto.

Yleiset vakiolausekkeet

C++:lla on aina ollut vakiolausekkeiden käsite. Näin ollen lausekkeet, kuten 3+4 , palauttivat aina samat tulokset aiheuttamatta sivuvaikutuksia. Itse vakiolausekkeet tarjoavat kätevän tavan C++-kääntäjille optimoida kääntämisen tulos. Kääntäjät arvioivat tällaisten lausekkeiden tulokset vasta käännöshetkellä ja tallentavat jo lasketut tulokset ohjelmaan. Siten tällaiset lausekkeet arvioidaan vain kerran. On myös muutamia tapauksia, joissa kielistandardi edellyttää vakiolausekkeiden käyttöä. Tällaisia ​​tapauksia voivat olla esimerkiksi ulkoisten taulukoiden tai enum-arvojen määritelmät.


int GiveFive () { return 5 ;} int jokin_arvo [ AnnaFive () + 7 ]; // luo 12 kokonaisluvun taulukko; kielletty C++:ssa

Yllä oleva koodi on laitonta C++:ssa, koska GiveFive() + 7 ei ole teknisesti käännöshetkellä tunnettu vakiolauseke. Kääntäjä ei vain tiedä tuolloin, että funktio todella palauttaa vakion ajon aikana. Syy tähän kääntäjän päättelyyn on, että tämä funktio voi vaikuttaa globaalin muuttujan tilaan, kutsua toista ei-vakiota ajonaikaista funktiota ja niin edelleen.

C++11 ottaa käyttöön avainsanan constexpr , jonka avulla käyttäjä voi varmistaa, että joko funktio tai objektikonstruktori palauttaa käännösaikavakion. Yllä oleva koodi voidaan kirjoittaa uudelleen seuraavasti:

constexpr int GiveFive () { return 5 ;} int jokin_arvo [ AnnaFive () + 7 ]; // luo 12 kokonaisluvun taulukko; sallittu C++11:ssä

Tämän avainsanan avulla kääntäjä voi ymmärtää ja varmistaa, että GiveFive palauttaa vakion.

Constexprin käyttö asettaa erittäin tiukat rajoitukset funktion toimiin:

  1. tällaisen funktion on palautettava arvo;
  2. funktion rungon on oltava muotoa paluulauseke ;
  3. lausekkeen on koostuttava vakioista ja/tai kutsuista muille constexpr- funktioille;
  4. constexpr: llä merkittyä funktiota ei voida käyttää ennen kuin se on määritetty nykyisessä käännösyksikössä.

Standardin aiemmassa versiossa vakiolausekkeissa voitiin käyttää vain kokonaisluku- tai enum-tyyppisiä muuttujia. C++11:ssä tämä rajoitus poistetaan muuttujilta, joiden määritelmää edeltää avainsana constexpr:

constexpr double accelerationOfGravity = 9,8 ; constexpr double moonGravity = accelrationOfGravity / 6 ;

Tällaisten muuttujien katsotaan jo implisiittisesti olevan const - avainsanalla . Ne voivat sisältää vain vakiolausekkeiden tulokset tai tällaisten lausekkeiden konstruktorit.

Jos on tarpeen rakentaa vakioarvoja käyttäjän määrittämistä tyypeistä, tällaisten tyyppien konstruktorit voidaan myös ilmoittaa käyttämällä constexpr . Vakiolausekkeen konstruktori, kuten vakiofunktiot, on myös määritettävä ennen sen ensimmäistä käyttöä nykyisessä käännösyksikössä. Tällaisella konstruktorilla tulee olla tyhjä runko, ja sellaisen konstruktorin tulee alustaa tyyppinsä jäsenet vain vakioilla.

Muutoksia yksinkertaisen tiedon määritelmään

Normaalissa C++:ssa vain rakenteita, jotka täyttävät tietyt säännöt, voidaan pitää tavallisena vanhana tietotyyppinä ( POD). On hyviä syitä odottaa, että näitä sääntöjä laajennetaan niin, että useampia tyyppejä katsotaan POD:iksi. Nämä säännöt täyttäviä tyyppejä voidaan käyttää C-yhteensopivassa objektikerroksen toteutuksessa, mutta C++03:n luettelo näistä säännöistä on liian rajoittava.

C++11 lieventää useita yksinkertaisten tietotyyppien määrittelyä koskevia sääntöjä.

Luokkaa pidetään yksinkertaisena tietotyyppinä, jos se on triviaali , sillä on vakioasettelu ( standard-layout ) ja jos kaikkien sen ei-staattisten tietojäsenten tyypit ovat myös yksinkertaisia ​​tietotyyppejä.

Triviaaliluokka on luokka, joka:

  1. sisältää triviaalin oletuskonstruktorin,
  2. ei sisällä ei-triviaaleja kopiokonstruktoreja,
  3. ei sisällä ei-triviaaleja siirtokonstruktoreja,
  4. ei sisällä ei-triviaaleja kopioiden määritysoperaattoreita,
  5. ei sisällä ei-triviaaleja siirtotehtäväoperaattoreita,
  6. sisältää triviaalin tuhoajan.

Normaalisijoitusluokka on luokka, joka:

  1. ei sisällä ei-staattisia tietojäseniä mukautetun luokkatyypin (tai kyseisen tyypin elementtien joukon) tai viitetyypin,
  2. ei sisällä virtuaalisia toimintoja,
  3. ei sisällä virtuaalisia perusluokkia,
  4. on sama saavutettavuustyyppi ( public, private, protected) kaikille ei-staattisille datajäsenille,
  5. sillä ei ole perusluokkia, joissa on epätyypillinen sijoitus,
  6. ei ole luokka, joka sisältää samanaikaisesti periytyviä ja ei-periytyviä ei-staattisia datajäseniä tai sisältää ei-staattisia datajäseniä, jotka on peritty useista perusluokista kerralla,
  7. sillä ei ole samantyyppisiä perusluokkia kuin ensimmäisellä ei-staattisella datajäsenellä (jos sellainen on).

Nopeuta kokoamista

Ulkoiset mallit

Normaalissa C++:ssa kääntäjän on luotava malli aina, kun se kohtaa täyden erikoistumisensa käännösyksikköön. Tämä voi pidentää merkittävästi käännösaikaa, varsinkin kun malliin instantioidaan samoilla parametreilla useissa käännösyksiköissä. Tällä hetkellä ei ole mitään keinoa kertoa C++:lle, ettei ilmentymistä pitäisi olla.

C++11 esitteli ajatuksen ulkoisista malleista. C++:ssa on jo syntaksi, joka kertoo kääntäjälle, että malli tulee instantoida tietyssä vaiheessa:

mallin luokka std :: vektori < MyClass > ;

C++:lta puuttuu kyky estää kääntäjää luomasta mallia käännösyksikössä. C++11 yksinkertaisesti laajentaa tätä syntaksia:

extern template class std :: vektori < MyClass > ;

Tämä lauseke käskee kääntäjää olemaan instantoimatta mallia tässä käännösyksikössä.

Parempi käytettävyys

Nämä ominaisuudet on tarkoitettu helpottamaan kielen käyttöä. Niiden avulla voit vahvistaa tyyppiturvallisuutta, minimoi koodin päällekkäisyyksiä, vaikeuttaa koodin väärinkäyttöä ja niin edelleen.

Alustusluettelot

Alustuslistojen käsite tuli C++:aan C:stä. Ajatuksena on, että rakenne tai taulukko voidaan luoda välittämällä argumenttiluettelo samassa järjestyksessä kuin rakenteen jäsenet määritellään. Alustuslistat ovat rekursiivisia, mikä mahdollistaa niiden käyttämisen rakenteille ja sisäkkäisiä rakenteita sisältäville rakenteille.

rakenneobjekti _ { kellua ensin ; int toinen ; }; Objektin skalaari = { 0,43f , 10 }; // yksi objekti, jossa ensimmäinen=0.43f ja toinen=10 Object anArray [] = {{ 13.4f , 3 }, { 43.28f , 29 }, { 5.934f , 17 }}; // kolmen objektin joukko

Alustusluettelot ovat erittäin hyödyllisiä staattisille listoille ja kun haluat alustaa rakenteen tiettyyn arvoon. C++ sisältää myös konstruktoreita, jotka voivat sisältää yleisen objektien alustustyön. C++-standardi sallii alustusluetteloiden käytön rakenteille ja luokille, mikäli ne ovat POD (Plain Old Data) -määritelmän mukaisia. Muut kuin POD-luokat eivät voi käyttää alustusluetteloita alustukseen, mukaan lukien standardi C++ -säiliöt, kuten vektorit.

C++11 on liittänyt käsitteen alustusluettelot ja malliluokka nimeltä std::initializer_list . Tämä antoi rakentajille ja muille funktioille mahdollisuuden vastaanottaa alustusluetteloita parametreina. Esimerkiksi:

luokka SequenceClass { julkinen : SequenceClass ( std :: alustusluettelo < int > lista ); };

Tämän kuvauksen avulla voit luoda SequenceClass -luokan kokonaislukujen sarjasta seuraavasti:

SequenceClass someVar = { 1 , 4 , 5 , 6 };

Tämä osoittaa, kuinka erityinen konstruktori toimii alustusluettelossa. Tällaisia ​​rakentajia sisältäviä luokkia käsitellään erityisellä tavalla alustuksen aikana (katso alla ).

Std ::initializer_list<> -luokka on määritelty C++11-standardikirjastossa. Tämän luokan objekteja voi kuitenkin luoda staattisesti vain C++11-kääntäjällä {} hakasulkeiden syntaksilla. Luettelo voidaan kopioida luomisen jälkeen, mutta tämä kopioidaan viitteellä. Alustuslista on vakio: sen jäseniä tai niiden tietoja ei voi muuttaa luomisen jälkeen.

Koska std::initializer_list<> on täysi tyyppi, sitä voidaan käyttää muussakin kuin vain rakentajissa. Tavalliset funktiot voivat ottaa kirjoitetut alustusluettelot argumenttina, esimerkiksi:

void FunctionName ( std :: alustusluettelo < float > lista ); FunctionName ({ 1.0f , -3.45f , -0.4f });

Vakiosäiliöt voidaan alustaa seuraavasti:

std :: vektori < std :: merkkijono > v = { "xyzzy" , "plugh" , "abracadabra" }; std :: vektori < std :: string > v { "xyzzy" , "plugh" , "abracadabra" }; Yleinen alustus

C++-standardi sisältää useita tyypin alustukseen liittyviä ongelmia. On olemassa useita tapoja alustaa tyyppejä, eivätkä ne kaikki johda samoihin tuloksiin. Esimerkiksi alustavan rakentajan perinteinen syntaksi saattaa näyttää funktion määrittelyltä, ja on oltava erityisen huolellinen, jotta kääntäjä ei jäsentä sitä väärin. Vain aggregaattityyppejä ja POD-tyyppejä voidaan alustaa koontialustajalla (tyyppisillä SomeType var = {/*stuff*/};).

C++11 tarjoaa syntaksin, joka mahdollistaa yhden alustuksen muodon käytön kaikenlaisille objekteille laajentamalla alustusluettelon syntaksia:

struct BasicStruct { int x ; kaksinkertainen y ; }; struct AltStruct { AltStruct ( int x , double y ) : x_ ( x ), y_ ( y ) {} yksityinen : int x_ ; kaksinkertainen y_ ; }; BasicStruct var1 { 5 , 3.2 }; AltStruct var2 { 2 , 4.3 };

Var1 :n alustus toimii täsmälleen samalla tavalla kuin aggregaattien alustus, eli jokainen objekti alustetaan kopioimalla vastaava arvo alustusluettelosta. Tarvittaessa käytetään implisiittistä tyyppimuunnosa. Jos haluttua muunnosa ei ole, lähdekoodia pidetään virheellisenä. Var2 : n alustuksen aikana konstruktoria kutsutaan.

Koodi on mahdollista kirjoittaa näin:

struct IdString { std :: merkkijonon nimi ; _ int tunniste ; }; IdString GetString () { return { "SomeName" , 4 }; // Huomaa selkeän tyyppien puute }

Yleinen alustus ei täysin korvaa rakentajan alustussyntaksia. Jos luokassa on konstruktori, joka ottaa alustusluettelon ( TyypinNimi(alustajaluettelo<JokinTyyppi>); ) argumenttina, se on etusijalla muihin objektin luontivaihtoehtoihin nähden. Esimerkiksi C++11 :ssä std::vector sisältää konstruktorin, joka ottaa alustusluettelon argumenttina:

std :: vektori < int > theVec { 4 };

Tämä koodi johtaa konstruktorikutsuun, joka käyttää alustusluetteloa argumenttina yhden parametrin rakentajan sijaan, joka luo tietyn kokoisen säilön. Tämän rakentajan kutsumiseksi käyttäjän on käytettävä rakentajan kutsusyntaksia.

Tyyppipäätelmä

Standardissa C++ (ja C) muuttujan tyyppi on määritettävä eksplisiittisesti. Mallityyppien ja mallien metaohjelmointitekniikoiden myötä joidenkin arvojen tyyppiä, erityisesti funktion palautusarvoja, ei kuitenkaan voida määrittää helposti. Tämä johtaa vaikeuksiin välitietojen tallentamisessa muuttujiin, joskus voi olla tarpeen tuntea tietyn metaohjelmointikirjaston sisäinen rakenne.

C++11 tarjoaa kaksi tapaa lieventää näitä ongelmia. Ensinnäkin eksplisiittisesti alustettavan muuttujan määritelmä voi sisältää automaattisen avainsanan . Tämä johtaa alustusarvon tyyppisen muuttujan luomiseen:

auto someStrangeCallableType = std :: bind ( & SomeFunction , _2 , _1 , someObject ); auto otherVariable = 5 ;

Tyypistä someStrangeCallableType tulee tyyppi, jonka mallifunktion konkreettinen toteutus palauttaa std::bindannetuille argumenteille. Kääntäjä määrittää tämän tyypin helposti semanttisen analyysin aikana, mutta ohjelmoijan on tehtävä tutkimusta tyypin määrittämiseksi.

Myös OtherVariable -tyyppi on hyvin määritelty, mutta ohjelmoija voi yhtä helposti määrittää sen. Tämä tyyppi on int , sama kuin kokonaislukuvakio.

Lisäksi decltype- avainsanaa voidaan käyttää määrittämään lausekkeen tyyppi käännöshetkellä . Esimerkiksi:

int someInt ; decltype ( someInt ) otherIntegerVariable = 5 ;

Decltype :n käyttö on hyödyllisintä yhdessä auto :n kanssa , koska muuttujan tyyppi, joka on ilmoitettu autoksi , on vain kääntäjän tiedossa . Myös decltypen käyttö voi olla varsin hyödyllistä lausekkeissa, jotka käyttävät operaattorin ylikuormitusta ja mallien erikoistumista.

autovoidaan käyttää myös koodin redundanssin vähentämiseen. Esimerkiksi sen sijaan:

for ( vektori < int >:: const_iterator itr = myvec . cbegin (); itr != myvec . cend (); ++ itr )

ohjelmoija osaa kirjoittaa:

for ( auto itr = myvec . cbegin (); itr != myvec . cend (); ++ itr )

Ero tulee erityisen havaittavaksi, kun ohjelmoija käyttää suurta määrää erilaisia ​​säiliöitä, vaikka silti on olemassa hyvä tapa vähentää ylimääräistä koodia typedef.

Decltype -merkillä merkitty tyyppi voi olla erilainen kuin auto .

#sisällytä <vektori> int main () { const std :: vektori < int > v ( 1 ); auto a = v [ 0 ]; // kirjoita a - int decltype ( v [ 0 ]) b = 1 ; // tyyppi b - const int& (palautusarvo // std::vektori<int>::operaattori[](kokotyyppi) const) auto c = 0 ; // kirjoita c - int auto d = c ; // tyyppi d - int decltype ( c ) e ; // kirjoita e - int, entiteetin tyyppi nimeltä c decltype (( c )) f = c ; // tyyppi f on int& koska (c) on lvvalue decltype ( 0 ) g ; // tyyppi g on int, koska 0 on rarvo } For-silmukka kokoelman läpi

Normaalissa C++ :ssa kokoelman elementtien iterointi vaatii paljon koodia . Joissakin kielissä, kuten C# , on toiminnot, jotka tarjoavat " foreach " -lausekkeen , joka käy automaattisesti läpi kokoelman elementit alusta loppuun. C++11 esittelee samanlaisen toiminnon. For- lause helpottaa elementtikokoelman iterointia:

int oma_taulukko [ 5 ] = { 1 , 2 , 3 , 4 , 5 }; for ( int & x : my_array ) { x *= 2 ; }

Tämä for-muoto, jota kutsutaan englanniksi "range-based for", vierailee kokoelman jokaisessa elementissä. Tämä koskee C - taulukoita , alustusluetteloita ja kaikkia muita tyyppejä , joissa on toimintoja begin()ja end()jotka palauttavat iteraattoreita . Kaikki vakiokirjaston säilöt , joilla on alku/loppu-pari, toimivat for-lausekkeen kanssa kokoelmassa.

Tällainen sykli toimii myös esimerkiksi C-tyyppisten taulukoiden kanssa, koska C++11 esittelee keinotekoisesti heille tarvittavat pseudomenetelmät (alku, loppu ja jotkut muut).

// klassisen taulukon aluepohjainen läpikulku int arr1 [] = { 1 , 2 , 3 }; for ( auto el : arr1 ); Lambdafunktiot ja lausekkeet

Normaalissa C++:ssa esimerkiksi käytettäessä tavallisia C++-kirjastoalgoritmeja lajittele ja löydä , on usein tarve määritellä predikaattifunktiot lähellä algoritmin kutsua. Tätä varten kielessä on vain yksi mekanismi: kyky määritellä funktionaaliluokka (funktion sisällä määritellyn luokan esiintymän välittäminen algoritmeille on kielletty (Meyers, Effective STL)). Usein tämä menetelmä on liian redundantti ja monisanainen ja vain vaikeuttaa koodin lukemista. Lisäksi funktioissa määriteltyjen luokkien standardit C++-säännöt eivät salli niiden käyttämistä malleissa ja tekevät niiden käytöstä siten mahdotonta.

Ilmeinen ratkaisu ongelmaan oli sallia lambda-lausekkeiden ja lambda-funktioiden määrittely C++11:ssä. Lambda-funktio määritellään seuraavasti:

[]( int x , int y ) { return x + y ; }

Tämän nimettömän funktion palautustyyppi lasketaan muodossa decltype(x+y) . Palautustyyppi voidaan jättää pois vain, jos lambda-funktio on muotoa . Tämä rajoittaa lambda-funktion koon yhteen lausekkeeseen. return expression

Palautustyyppi voidaan määrittää eksplisiittisesti, esimerkiksi:

[]( int x , int y ) -> int { int z = x + y ; paluu z ; }

Tämä esimerkki luo väliaikaisen muuttujan z väliarvon tallentamiseksi. Kuten tavallisten toimintojen kohdalla, tämä väliarvo ei säily puheluiden välillä.

Palautustyyppi voidaan jättää kokonaan pois, jos funktio ei palauta arvoa (eli palautustyyppi on void )

On myös mahdollista käyttää viittauksia muuttujiin, jotka on määritelty samassa laajuudessa kuin lambda-funktio. Tällaisten muuttujien joukkoa kutsutaan yleensä sulkemiseksi . Sulkemiset määritellään ja niitä käytetään seuraavasti:

std :: vektori < int > someList ; kokonaissumma = 0 ; _ std :: for_each ( someList . begin (), someList . end (), [ & total ]( int x ) { yhteensä += x ; }); std :: cout << yhteensä ;

Tämä näyttää luettelon kaikkien elementtien summan. Kokonaismuuttuja tallennetaan osana lambda-funktion sulkemista . Koska se viittaa pinomuuttujaan total , se voi muuttaa sen arvoa.

Paikallisten muuttujien sulkemismuuttujat voidaan määrittää myös ilman viitesymbolia & , mikä tarkoittaa, että funktio kopioi arvon. Tämä pakottaa käyttäjän ilmoittamaan aikomuksensa viitata paikalliseen muuttujaan tai kopioida sitä.

Lambda-funktioissa, joiden suoritus on taattu laajuudessaan, on mahdollista käyttää kaikkia pinomuuttujia ilman erityisiä viittauksia niihin:

std :: vektori < int > someList ; kokonaissumma = 0 ; _ std :: for_each ( someList . begin (), someList . end (), [ & ]( int x ) { yhteensä += x ; });

Toteutustavat voivat vaihdella sisäisesti, mutta lambda-funktion odotetaan tallentavan osoittimen sen funktion pinoon, jossa se luotiin, sen sijaan, että se toimisi yksittäisten pinomuuttujien viittausten perusteella.

Jos sen sijaan [&]käytetään [=], kaikki käytetyt muuttujat kopioidaan, jolloin lambda-funktiota voidaan käyttää alkuperäisten muuttujien ulkopuolella.

Oletussiirtotapaa voidaan myös täydentää yksittäisten muuttujien luettelolla. Jos sinun on esimerkiksi välitettävä suurin osa muuttujista viitteellä ja yksi arvolla, voit käyttää seuraavaa rakennetta:

kokonaissumma = 0 ; _ int arvo = 5 ; [ & , arvo ]( int x ) { yhteensä += ( x * arvo ); } ( 1 ); //(1) kutsu lambda-funktiota arvolla 1

Tämä aiheuttaa sen, että summa välitetään viitteellä ja arvo arvolla.

Jos lambda-funktio on määritelty luokkametodissa, sitä pidetään kyseisen luokan ystävänä. Tällaiset lambda-funktiot voivat käyttää viittausta luokkatyyppiseen objektiin ja käyttää sen sisäisiä kenttiä:

[]( SomeType * typePtr ) { typePtr -> SomePrivateMemberFunction (); }

Tämä toimii vain, jos lambda-funktion laajuus on luokkamenetelmä SomeType .

Työskentely tämän osoittimen kanssa objektiin, jonka kanssa nykyinen menetelmä on vuorovaikutuksessa, toteutetaan erityisellä tavalla. Se on merkittävä nimenomaisesti lambda-funktioon:

[ this ]() { this -> SomePrivateMemberFunction (); }

Lomakkeen [&]tai [=]lambda-toiminnon avulla tämä on käytettävissä automaattisesti.

Lambda-toimintojen tyyppi riippuu toteutuksesta; tämän tyypin nimi on vain kääntäjän käytettävissä. Jos sinun on välitettävä lambda-funktio parametrina, sen on oltava mallityyppiä tai tallennettu std::funktiolla . Automaattisen avainsanan avulla voit tallentaa lambda-funktion paikallisesti:

auto myLambdaFunc = [ this ]() { this -> SomePrivateMemberFunction (); };

Lisäksi, jos funktio ei ota argumentteja, ()voit jättää pois:

auto myLambdaFunc = []{ std :: cout << "hei" << std :: endl ; }; Vaihtoehtoisen funktion syntaksi

Joskus on tarpeen toteuttaa funktiomalli, joka johtaisi lausekkeeseen, jolla on sama tyyppi ja sama arvoluokka kuin jollain muulla lausekkeella.

malli < typename LHS , typename RHS > RETURN_TYPE AddingFunc ( const LHS & lhs , const RHS & rhs ) // mitä RETURN_TYPE pitäisi olla? { paluu lhs + rhs ; }

Jotta lausekkeella AddingFunc(x, y) olisi sama tyyppi ja sama arvoluokka kuin lausekkeella lhs + rhs , kun argumentit x ja y annettaisiin , C++11:ssä voidaan käyttää seuraavaa määritelmää:

malli < typename LHS , typename RHS > decltype ( std :: declval < const LHS &> () + std :: declval < const RHS &> ()) AddingFunc ( const LHS & lhs , const RHS & rhs ) { paluu lhs + rhs ; }

Tämä merkintä on hieman hankala, ja olisi mukavaa käyttää lhs- ja rhs-arvoja std::declval<const LHS &>() ja std::declval<const RHS &>() sijasta. Kuitenkin seuraavassa versiossa

malli < typename LHS , typename RHS > decltype ( lhs + rhs ) AddingFunc ( const LHS & lhs , const RHS & rhs ) // Ei voimassa C++11 { paluu lhs + rhs ; }

Ihmisen luettavampi, decltype-operandissa käytetyt lhs- ja rhs-tunnisteet eivät voi merkitä myöhemmin ilmoitettuja vaihtoehtoja. Tämän ongelman ratkaisemiseksi C++11 ottaa käyttöön uuden syntaksin funktioiden ilmoittamiseen, jonka lopussa on palautustyyppi:

malli < typename LHS , typename RHS > auto AddingFunc ( const LHS & lhs , const RHS & rhs ) -> decltype ( lhs + rhs ) { paluu lhs + rhs ; }

On kuitenkin huomattava, että alla olevassa yleisemmässä AddingFunc-toteutuksessa uusi syntaksi ei hyödy lyhyydestä:

malli < typename LHS , typename RHS > auto AddingFunc ( LHS && lhs , RHS && rhs ) -> decltype ( std :: eteenpäin < LHS > ( lhs ) + std :: eteenpäin < RHS > ( rhs )) { paluu std :: eteenpäin < LHS > ( lhs ) + std :: eteenpäin < RHS > ( rhs ); } malli < typename LHS , typename RHS > auto AddingFunc ( LHS && lhs , RHS && rhs ) -> decltype ( std :: declval < LHS > () + std :: declval < RHS > ()) // sama vaikutus kuin std::eteenpäin edellä { paluu std :: eteenpäin < LHS > ( lhs ) + std :: eteenpäin < RHS > ( rhs ); } malli < typename LHS , typename RHS > decltype ( std :: declval < LHS > () + std :: declval < RHS > ()) // sama vaikutus kuin kirjoittamalla tyyppi loppuun AddingFunc ( LHS && lhs , RHS && rhs ) { paluu std :: eteenpäin < LHS > ( lhs ) + std :: eteenpäin < RHS > ( rhs ); }

Uutta syntaksia voidaan käyttää yksinkertaisemmissa ilmoituksissa ja ilmoituksissa:

rakentaa SomeStruct { auto FuncName ( int x , int y ) -> int ; }; auto SomeStruct :: FuncName ( int x , int y ) -> int { paluu x + y _ }

Avainsanan " " autokäyttö tarkoittaa tässä tapauksessa vain myöhäistä ilmoitusta palautustyypistä, eikä se liity sen automaattiseen päättelyyn.

Objektien rakentajien parantaminen

Standardi C++ ei salli yhden luokan konstruktoria kutsua toisesta saman luokan konstruktorista; Jokaisen rakentajan on alustattava täysin kaikki luokan jäsenet tai kutsuttava luokan menetelmiä tehdäkseen niin. Luokan ei-vakiojäseniä ei voida alustaa paikassa, jossa kyseiset jäsenet on ilmoitettu.

C++11 pääsee eroon näistä ongelmista.

Uusi standardi sallii yhden luokan konstruktorin kutsumisen toisesta (ns. delegaatio). Tämän avulla voit kirjoittaa rakentajia, jotka käyttävät muiden rakentajien käyttäytymistä ilman päällekkäistä koodia.

Esimerkki:

class SomeType { int numero ; julkinen : SomeType ( int uusi_numero ) : numero ( uusi_numero ) {} SomeType ( ) : SomeType ( 42 ) {} };

Esimerkistä voit nähdä, että rakentaja SomeTypeilman argumentteja kutsuu saman luokan konstruktoria kokonaislukuargumentilla alustaakseen muuttujan number. Samanlainen vaikutus voitaisiin saavuttaa määrittämällä tälle muuttujalle sen ilmoituksessa alkuarvo 42.

class SomeType { int numero = 42 ; julkinen : SomeType () {} eksplisiittinen SomeType ( int uusi_numero ) : numero ( uusi_numero ) {} };

Mikä tahansa luokan rakentaja alustaa numberarvon 42, jos se ei itse anna sille eri arvoa.

Java , C# ja D ovat esimerkkejä kielistä, jotka myös ratkaisevat nämä ongelmat .

On huomattava, että jos C++03:ssa objektin katsotaan olevan täysin luotu, kun sen konstruktori on suorittanut suorituksen, niin C++11:ssä, kun vähintään yksi delegoiva konstruktori on suoritettu, loput konstruktorit työskentelevät täysin rakennettu esine. Tästä huolimatta johdetun luokan objektit rakennetaan vasta, kun kaikki perusluokkien konstruktorit on suoritettu.

Virtuaalitoimintojen eksplisiittinen korvaaminen ja lopullisuus

On mahdollista, että virtuaalisen menetelmän allekirjoitus on muutettu perusluokassa tai asetettu väärin johdettuun luokassa alun perin. Tällaisissa tapauksissa annettu menetelmä johdetussa luokassa ei ohita vastaavaa menetelmää perusluokassa. Joten jos ohjelmoija ei muuta menetelmän allekirjoitusta oikein kaikissa johdetuissa luokissa, menetelmää ei ehkä kutsuta oikein ohjelman suorittamisen aikana. Esimerkiksi:

struct Base { virtuaalinen void some_func (); }; struct Johdettu : Base { void sone_func (); };

Tässä johdetussa luokassa ilmoitettu virtuaalisen funktion nimi on kirjoitettu väärin, joten tällainen funktio ei ohita Base::some_func, eikä sitä siksi kutsuta polymorfisesti osoittimen tai viittauksen kautta perusaliobjektiin.

C++11 lisää mahdollisuuden seurata näitä ongelmia käännösaikana (ajon aikana). Tämä ominaisuus on valinnainen taaksepäin yhteensopivuuden vuoksi. Uusi syntaksi näkyy alla:

rakenne B { virtuaalinen void some_func (); virtuaalinen void f ( int ); virtuaalinen void g () const ; }; rakenne D1 : julkinen B { void sone_func () ohitus ; // virhe: virheellinen funktion nimi void f ( int ) override ; // OK: ohittaa saman funktion perusluokassa virtual void f ( long ) override ; // virhe: parametrityyppi ei täsmää virtual void f ( int ) const override ; // error: function cv-qualification mismatch virtual int f ( int ) override ; // virhe: paluutyyppi ei täsmää virtual void g () const final ; // OK: ohittaa saman funktion perusluokassa virtual void g ( long ); // OK: uusi virtuaalifunktio }; rakenne D2 : D1 { virtuaalinen void g () const ; // virhe: yritä korvata lopullinen funktio };

Virtuaalifunktion määritteen olemassaolo finaltarkoittaa, että sen korvaaminen on mahdotonta. Myöskään lopullisella määritteellä määritettyä luokkaa ei voi käyttää perusluokkana:

struct F lopullinen { int x , y ; }; struct D : F // virhe: periytyminen lopullisista luokista ei sallittu { int z ; };

Tunnisteilla overrideja finalon erityinen merkitys vain, kun niitä käytetään tietyissä tilanteissa. Muissa tapauksissa niitä voidaan käyttää normaaleina tunnisteina (esimerkiksi muuttujan tai funktion nimenä).

Nollaosoittimen vakio

C:n ilmestymisestä vuonna 1972 lähtien vakiolla 0 on ollut kokonaisluvun ja nollaosoittimen kaksoisrooli. Yksi tapa käsitellä tätä C-kielelle ominaista monitulkintaisuutta on makro NULL, joka tyypillisesti suorittaa ((void*)0)tai korvauksen 0. C++ eroaa C:stä tässä suhteessa sallien vain 0nollaosoittimen käytön vakiona. Tämä johtaa huonoon vuorovaikutukseen toimintojen ylikuormituksen kanssa:

void foo ( char * ); void foo ( int );

Jos makro NULLon määritelty 0(joka on yleistä C++:ssa), rivi foo(NULL);johtaa kutsuun foo(int), ei foo(char *)niin kuin pikakatselu koodiin saattaisi ehdottaa, mikä ei läheskään varmasti ole ohjelmoijan tarkoitus.

Yksi C++11:n uutuuksista on uusi avainsana kuvaamaan nollaosoittimen vakiota - nullptr. Tämä vakio on tyyppiä std::nullptr_t, joka voidaan implisiittisesti muuntaa minkä tahansa osoittimen tyypiksi ja verrata mihin tahansa osoittimeen. Implisiittistä muuntamista integraalityypiksi ei sallita, paitsi bool. Alkuperäinen standardiehdotus ei sallinut implisiittistä muuntamista loogisiksi, mutta standardiluonnosryhmä salli tällaiset muunnokset yhteensopivuuden vuoksi tavanomaisten osoitintyyppien kanssa. Ehdotettua sanamuotoa muutettiin yksimielisen äänestyksen jälkeen kesäkuussa 2008 [1] .

Taaksepäin yhteensopivuuden vuoksi vakiota 0voidaan käyttää myös nollaosoittimena.

char * pc = nullptr ; // true int * pi = nullptr ; // true bool b = nullptr ; // oikein. b = false. int i = nullptr ; // virhe foo ( nullptr ); // kutsuu foo(char *), ei foo(int);

Usein rakenteet, joissa osoitin on taatusti tyhjä, ovat yksinkertaisempia ja turvallisempia kuin muut - joten voit ylikuormittaa . nullptr_t

luokka Hyötykuorma ; class SmartPtr { SmartPtr () = oletus ; SmartPtr ( nullptr_t ) {} // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< eksplisiittinen SmartPtr ( hyötykuorma * aData ) : fData ( aData ) {} // kopioi rakentajat ja op= jättää pois ~ SmartPtr () { delete fData ; } yksityinen : Hyötykuorma * fData = nullptr ; } SmartPtr getPayload1 () { return nullptr ; } // SmartPtr(nullptr_t) overload kutsutaan. Voimakkaasti kirjoitetut enumit

Normaalissa C++:ssa enumit eivät ole tyyppiturvallisia. Itse asiassa niitä edustavat kokonaisluvut huolimatta siitä, että itse luettelointityypit eroavat toisistaan. Tämä mahdollistaa kahden arvon vertailun eri enumeista. Ainoa vaihtoehto, jonka C++03 tarjoaa enumeiden suojaamiseen, on olla implisiittisesti muuntamatta yhden enumin kokonaislukuja tai elementtejä toisen enum-elementeiksi. Myös tapa, jolla se esitetään muistissa (kokonaislukutyyppi), on toteutuksesta riippuvainen eikä siksi ole kannettava. Lopuksi luetteloelementeillä on yhteinen laajuus, mikä tekee mahdottomaksi luoda samannimisiä elementtejä eri luetteloissa.

C++11 tarjoaa näille enumeille erityisen luokituksen, joka ei sisällä yllä olevia haittoja. Tällaisten luetteloiden kuvaamiseen käytetään ilmoitusta enum class(se voidaan käyttää enum structmyös synonyyminä):

enum luokkaluettelo { _ Val1 , Val2 , Val3 = 100 , Val4 , /* = 101 */ };

Tällainen luettelo on tyyppiturvallinen. Luokan enum-elementtejä ei voida implisiittisesti muuntaa kokonaisluvuiksi. Tämän seurauksena myös vertailu kokonaislukuihin on mahdotonta (lauseke Enumeration::Val4 == 101johtaa käännösvirheeseen).

Luokkaluettelotyyppi on nyt toteutuksesta riippumaton. Oletuksena, kuten yllä olevassa tapauksessa, tämä tyyppi on int, mutta muissa tapauksissa tyyppi voidaan asettaa manuaalisesti seuraavasti:

enum luokka Enum2 : unsigned int { Val1 , Val2 };

Enumin jäsenten laajuus määräytyy enumin nimen laajuuden mukaan. Elementtinimien käyttäminen edellyttää luokkaluettelon nimen määrittämistä. Joten esimerkiksi arvo Enum2::Val1on määritelty, mutta arvoa Val1 ei ole määritelty.

Lisäksi C++11 tarjoaa mahdollisuuden määritellä selkeästi laajuuden ja taustalla olevat tyypit tavallisille enumeille:

enum Enum3 : etumerkitön pitkä { Val1 = 1 , Val2 };

Tässä esimerkissä enum-elementtien nimet on määritetty enum-avaruudessa (Enum3::Val1), mutta taaksepäin yhteensopivuuden vuoksi elementtien nimet ovat saatavilla myös yhteisessä laajuudessa.

Myös C++11:ssä on mahdollista ennakkoilmoittaa enumeita. Aiemmissa C++-versioissa tämä ei ollut mahdollista, koska enumin koko riippui sen elementeistä. Tällaisia ​​ilmoituksia voidaan käyttää vain, kun luettelon koko on määritetty (eksplisiittisesti tai implisiittisesti):

enum Enum1 ; // ei kelpaa C++:lle ja C++11:lle; taustalla olevaa tyyppiä ei voida määrittää enum Enum2 : unsigned int ; // tosi C++11:lle, jonka taustalla oleva tyyppi on nimenomaisesti määritelty enum- luokka Enum3 ; // totta C++11:lle, taustalla oleva tyyppi on int enum- luokka Enum4 : unsigned int ; // totta C++11:lle. enum Enum2 : allekirjoittamaton lyhyt ; // ei kelpaa C++11:lle, koska Enum2 oli aiemmin ilmoitettu eri taustalla Kulmasulut

Tavalliset C++-jäsentimet määrittelevät aina ">>"-merkkiyhdistelmän oikealle siirtooperaattoriksi. Välilyönnin puuttuminen sulkevien kulmasulkujen välillä malliparametreissa (jos ne ovat sisäkkäisiä) käsitellään syntaksivirheenä.

C++11 parantaa jäsentimen toimintaa tässä tapauksessa siten, että useat suorakulmasulut tulkitaan sulkeviksi malliargumenttiluetteloiksi.

Kuvattu käyttäytyminen voidaan korjata vanhan lähestymistavan hyväksi sulkujen avulla.

malli < luokka T > luokka Y { /* ... */ }; Y < X < 1 >> x3 ; // Oikein, sama kuin "Y<X<1> > x3;". Y < X < 6 >> 1 >> x4 ; // Syntaksivirhe. Sinun on kirjoitettava "Y<X<(6>>1)>> x4;".

Kuten yllä näkyy, tämä muutos ei ole täysin yhteensopiva edellisen standardin kanssa.

Eksplisiittiset muunnosoperaattorit

C++-standardi tarjoaa avainsanan explicitmuuntajana yksiparametrisille rakentajille, jotta tällaiset konstruktorit eivät toimi implisiittisinä muunnoskonstruktoreina. Tämä ei kuitenkaan vaikuta varsinaisiin muunnosoperaattoreihin millään tavalla. Esimerkiksi älykäs osoitinluokka voi sisältää operator bool()normaalin osoittimen jäljittelemiseksi. Tällaista operaattoria voidaan kutsua esimerkiksi näin: if(smart_ptr_variable)(haara suoritetaan, jos osoitin ei ole nolla). Ongelmana on, että tällainen operaattori ei suojaa muilta odottamattomilta muunnoksilta. Koska tyyppi boolon ilmoitettu aritmeettiseksi tyypiksi C++:ssa, implisiittinen muunnos mihin tahansa kokonaislukutyyppiin tai jopa liukulukutyyppiin on mahdollista, mikä puolestaan ​​voi johtaa odottamattomiin matemaattisiin operaatioihin.

C++11:ssä avainsana explicitkoskee myös muunnosoperaattoreita. Kuten rakentajat, se suojaa odottamattomilta implisiittisiltä muunnoksilta. Tilanteet, joissa kieli kontekstuaalisesti odottaa loogista tyyppiä (esimerkiksi ehdollisissa lausekkeissa, silmukoissa ja loogisissa operaattorioperandeissa), katsotaan kuitenkin eksplisiittisiksi muunnoksiksi, ja eksplisiittinen bool-muunnosoperaattori kutsutaan suoraan.

Malli typedef

Normaalissa C++:ssa avainsanaa typedefvoidaan käyttää vain synonyymimääritelmänä toiselle tyypille, mukaan lukien synonyymi mallimäärittelylle, jossa on kaikki sen parametrit. Mutta mallin synonyymiä ei ole mahdollista luoda. Esimerkiksi:

malli < typename First , typename Toinen , int kolmas > luokka SomeType ; malli < typenameSecond > _ typedef SomeType < OtherType , Second , 5 > TypedefName ; // Ei mahdollista C++:ssa

Tätä ei käännetä.

C++11 lisäsi tämän ominaisuuden seuraavalla syntaksilla:

malli < typename First , typename Toinen , int kolmas > luokka SomeType ; malli < typenameSecond > _ käyttäen TypedefName = SomeType < OtherType , Second , 5 > ;

C++11:ssä direktiiviä usingvoidaan käyttää myös tietotyypin aliaksena.

typedef void ( * OtherType )( double ); // Vanha tyyli käyttäen OtherTypeä = void ( * )( double ); // Uusi syntaksi Rajoitusten poistaminen liitosta

Aiemmissa C++-standardeissa on useita rajoituksia luokkatyyppien jäsenten käytölle ammattiliitoissa. Erityisesti liitot eivät voi sisältää objekteja, joissa on ei-triviaali konstruktori. C++11 poistaa osan näistä rajoituksista. [2]

Tässä on yksinkertainen esimerkki liittämisestä, joka on sallittu C++11:ssä:

//sijoittelulle uusi #sisällytä < uusi> rakennepiste { _ Piste () {} Piste ( int x , int y ) : x_ ( x ), y_ ( y ) {} int x_ , y_ ; }; liitto U { int z ; kaksinkertainen w ; Piste p ; // Ei totta C++03:lle, koska Pointilla on ei-triviaali konstruktori. Koodi toimii kuitenkin oikein C++11:ssä. U () { uusi ( & p ) Piste (); } // Liitolle ei ole määritelty ei-triviaaleja menetelmiä. // Tarvittaessa ne voidaan poistaa, jotta manuaalinen määrittely toimii };

Muutokset eivät vaikuta olemassa olevaan koodiin, koska ne vain löystävät olemassa olevia rajoituksia.

Toiminnan laajentaminen

Tässä osiossa kuvataan uusia ominaisuuksia, jotka eivät olleet aiemmin saatavilla tai vaativat erityisiä ei-kannettavia kirjastoja.

Variable Argument Templates

Ennen C++11:tä mallit (luokkien tai funktioiden) saattoivat ottaa vain tietyn määrän argumentteja, jotka määriteltiin, kun malli alun perin ilmoitettiin. C++11:n avulla voit määrittää malleja, joissa on vaihteleva määrä minkä tahansa tyyppisiä argumentteja.

malli < tyypin nimi ... Arvot > luokka monikko ;

Esimerkiksi malliluokan monikko ( tuple ) hyväksyy minkä tahansa määrän tyyppinimiä malliparametreiksi:

luokan monikko < int , std :: vektori < int > , std :: kartta < std :: merkkijono , std :: vektori < int >>> jonkin_esiintymän_nimi ;

Argumentit saattavat puuttua, joten vaihtoehto class tuple<> some_instance_nametoimii myös.

Voit estää mallin ilmentymisen ilman argumentteja seuraavaa määritelmää:

template < typename First , typename ... Rest > class tuple ;

Muuttuja-argumenttimalleja voidaan käyttää myös funktioissa, mikä mahdollistaa niiden käytön variadic-funktioiden tyyppiturvallisissa muunnelmissa (kuten printf) ja ei-triviaalien objektien käsittelyssä.

template < typename ... Parametrit > void printf ( const std :: string & str_format , Params ... parametrit );

...-operaattorilla on kaksi roolia tässä. Paramien vasemmalla puolella käyttäjä ilmoittaa, että parametrit on pakattava. Pakattujen parametrien käyttö mahdollistaa 0 tai useamman argumentin liittämisen malliin. Pakattuja parametreja voidaan käyttää muuhunkin kuin vain tyyppinimien välittämiseen. Oikealla oleva ...-operaattori puolestaan ​​purkaa parametrit erillisiksi argumenteiksi (katso args...funktion runko alla olevassa esimerkissä).

On myös mahdollista käyttää rekursiivisesti malleja, joissa on vaihteleva määrä argumentteja. Yksi esimerkki olisi tyyppiturvallinen korvaaminen printf :lle :

void printf ( const char * s ) { while ( * s ) { if ( * s == '%' && * ( ++ s ) != '%' ) throw std :: runtime_error ( "virheellinen muotomerkkijono: puuttuvat argumentit" ); std :: cout << * s ++ ; } } malli < typename T , typename ... Args > void printf ( const char * s , T - arvo , Args ... args ) { while ( * s ) { if ( * s == '%' && * ( ++ s ) != '%' ) { std :: cout << arvo ; ++ s ; printf ( s , args ...); // jatka argumenttien käsittelyä, vaikka *s == 0 return ; } std :: cout << * s ++ ; } throw std :: logic_error ( "printf:lle tarjotaan lisäargumentteja" ); }

Tämä kuvio on rekursiivinen. Huomaa, että printf-funktio kutsuu ilmentymisen tuloksia tai perusprintf-funktiota, jos args... on tyhjä.

Ei ole helppoa tapaa ohittaa parametreja vaihtelevassa mallissa. Tästä huolimatta argumentin purkausoperaattorin käyttäminen kiertää tämän ongelman.

Luokka voidaan määritellä esimerkiksi näin:

template < typename ... BaseClasses > class ClassName : public BaseClasses ... { julkinen : LuokanNimi ( BaseClasses && ... base_classes ) : Perusluokat ( perusluokat )... {} };

Purkausoperaattori monistaa kaiken tyyppiset ClassNameyläluokat siten, että luokka peritään kaikista malliparametreissa määritellyistä tyypeistä. Lisäksi rakentajan on hyväksyttävä viittaus kaikkiin perusluokkiin, jotta jokainen pääperusluokka alustetaan ClassName.

Mallin parametrit voidaan ohjata uudelleen. Yhdessä rvalue-viittauksien kanssa (katso yllä), voit uudelleenohjata:

template < typename TypeToConstruct > struct SharedPtrAllocator { template < typename ... Args > std :: share_ptr < TypeToConstruct > construct_with_shared_ptr ( Args && ... params ) { return std :: shared_ptr < TypeToConstruct > ( new TypeToConstruct ( std :: forward < Args > ( params )...)); }; };

Tämä koodi purkaa argumenttiluettelon TypeToConstruct-konstruktoriin. Syntaksin std::forward<Args>(params)avulla voit täysin läpinäkyvästi uudelleenohjata argumentit rakentajalle niiden rvalue-luonteesta riippumatta. Toiminto kääri osoittimet automaattisesti sisään std::shared_ptrsuojatakseen muistivuotoja.

On myös mahdollista määrittää pakattujen argumenttien lukumäärä seuraavasti:

template < typename ... Args > struct SomeStruct { static const int koko = sizeof ...( Args ); };

Tässä se SomeStruct<Type1, Type2>::sizeon yhtä suuri kuin 2 ja SomeStruct<>::sizeyhtä suuri kuin 0.

Uudet merkkijonokirjaimet

C++03 tarjosi kahdenlaisia ​​merkkijonoliteraaaleja. Ensimmäinen tyyppi, kaksoislainausmerkkijono, on nollapäätteinen taulukko, jonka tyyppi on const char. Toinen tyyppi, joka määritellään nimellä L"", on nollapäätteinen matriisi tyyppiä const wchar_t, jossa wchar_ton määrittämättömien kokojen ja semantiikan laaja merkki. Mikään literaalityypeistä ei ole tarkoitettu tukemaan UTF-8- , UTF-16- merkkijonoliteraaaleja tai muita Unicode - koodauksia

Tyyppimäärittelyä charon muokattu niin, että se on vähintään se koko, joka tarvitaan kahdeksanbittisen UTF-8- koodauksen tallentamiseen , ja riittävän suuri sisältämään minkä tahansa merkin ajonaikaisessa merkistössä. Aiemmin standardissa tämä tyyppi määriteltiin yhdeksi merkiksi, myöhemmin C-kielen standardia seuraten, sen täytyi varata vähintään 8 bittiä.

C++11-standardi tukee kolmea Unicode-koodausta: UTF-8 , UTF-16 ja UTF-32 . Yllä olevien sisäänrakennetun merkkityypin muutosten lisäksi charC++11 lisää kaksi uutta merkkityyppiä: char16_tja char32_t. Ne on suunniteltu tallentamaan UTF-16- ja UTF-32-merkkejä.

Seuraavassa näytetään, kuinka luodaan merkkijonoliteraaleja kullekin näistä koodauksista:

u8 "Olen UTF-8-merkkijono." u "Tämä on UTF-16-merkkijono." U "Tämä on UTF-32-merkkijono."

Ensimmäisen rivin tyyppi on normaali const char[]. Toisen rivin tyyppi on const char16_t[]. Kolmannen rivin tyyppi on const char32_t[].

Kun muodostat Unicode-standardin merkkijonoliteraaaleja, on usein hyödyllistä lisätä Unicode-koodi suoraan merkkijonoon. Tätä varten C++11 tarjoaa seuraavan syntaksin:

u8 "Tämä on Unicode-merkki: \u2018 ." u "Tämä on suurempi Unicode-merkki: \u2018 ." U "Tämä on Unicode-merkki: \U00002018 ."

Tämän jälkeen olevan luvun \uon oltava heksadesimaali; etuliitettä ei tarvitse käyttää 0x. Tunniste \utarkoittaa 16-bittistä Unicode-koodia; 32-bittisen koodin \Usyöttämiseen käytetään myös 32-bittistä heksadesimaalilukua. Vain kelvollisia Unicode-koodeja voidaan syöttää. Esimerkiksi koodit alueella U+D800-U+DFFF eivät ole sallittuja, koska ne on varattu UTF-16-korvauspareille.

Joskus on myös hyödyllistä välttää merkkijonojen pakottamista manuaalisesti, erityisesti käytettäessä XML - tiedostoliteraaaleja, komentosarjakieliä tai säännöllisiä lausekkeita. Näihin tarkoituksiin C++11 tukee "raakoja" merkkijonoliteraaaleja:

R"(String Data \ Stuff " )" R"erotin(merkkijonotiedot \ jutut " )erotin"

Ensimmäisessä tapauksessa kaikki ja väliltä "(ja )"ovat osa merkkijonoa. Hahmoja "ja \niitä ei tarvitse paeta. Toisessa tapauksessa se "delimiter(aloittaa merkkijonon, ja se päättyy vasta saavuttaessaan )delimiter". Merkkijono delimitervoi olla mikä tahansa enintään 16 merkkiä pitkä merkkijono, tyhjä merkkijono mukaan lukien. Tämä merkkijono ei saa sisältää välilyöntejä, ohjausmerkkejä, ' (', ' )' tai merkkiä ' \'. Tämän erotinmerkkijonon käyttäminen mahdollistaa merkin ' )' käytön raakamerkkijonoliteraaaleissa. Se R"delimiter((a-z))delimiter"vastaa esimerkiksi "(a-z)"[3] .

"Raaka" merkkijonoliteraaleja voidaan yhdistää laajennettuun literaaliin (etuliite L"") tai mihin tahansa Unicode-literaalietuliitteeseen.

LR"(Raaka leveä merkkijono \t (ilman välilehteä))" u8R"XXX(olen "raaka UTF-8"-merkkijono.)XXX" uR"*(Tämä on "raaka UTF-16"-merkkijono.)*" UR"(Tämä on "raaka UTF-32"-merkkijono.)" Mukautetut literaalit

Mukautetut literaalit toteutetaan käyttämällä operaattorin ylikuormitusta operator"". Literaalit voivat olla tekstin sisäisiä tai constexpr-määritteitä . On toivottavaa, että kirjaimellinen alkaa alaviivalla, koska se voi olla ristiriidassa tulevien standardien kanssa. Esimerkiksi literaali i kuuluu jo kompleksilukuihin alkaen std::complex.

Literaalit voivat olla vain yhden seuraavista tyypeistä: const char * , unsigned long long int , long double , char , wchar_t , char16_t , char32_t. Literaalin ylikuormittaminen riittää vain tyypille const char * . Jos sopivaa ehdokasta ei löydy, kutsutaan kyseisen tyyppistä operaattoria. Esimerkki mailien muuntamisesta kilometreiksi:

constexpr int operaattori "" _mi ( unsigned long long int i ) { paluu 1.6 * i ;}

Merkkijonoliteraaleilla on toinen argumentti std::size_tja yksi ensimmäisistä: const char * , const wchar_t *, const char16_t * , const char32_t *. Merkkijonoliteraalit koskevat lainausmerkeissä olevia merkintöjä.

Monisäikeinen muistimalli

C++11 standardoi monisäikeisen ohjelmoinnin tuen. Mukana on kaksi osaa: muistimalli, joka sallii useiden säikeiden esiintymisen yhdessä ohjelmassa, ja kirjasto, joka tukee viestien välistä viestintää.

Muistimalli määrittää, kuinka useat säikeet voivat päästä samaan muistipaikkaan, ja määrittää, milloin yhden säikeen tekemät muutokset tulevat muiden säikeiden näkyviksi.

Säikeistetty tallennustila Eksplisiittinen oletus ja erikoismenetelmien poistaminen

Määritykset defaultja deletevoidaan määrittää menetelmän rungon sijaan.

luokka Foo { julkinen : foo () = oletusarvo ; Foo ( int x ) { /* ... */ } };

Määrite defaulttarkoittaa oletustoteutusta ja sitä voidaan soveltaa vain erityisiin jäsentoimintoihin:

  • oletus rakentaja;
  • kopio rakentaja;
  • siirtää rakentaja;
  • toimeksianto-operaattori;
  • siirtää operaattori;
  • tuhoaja.

Määrittäjä deletemerkitsee ne menetelmät, joilla ei voi työskennellä. Aiemmin tällaiset rakentajat piti ilmoittaa luokan yksityisessä piirissä.

luokka Foo { julkinen : foo () = oletusarvo ; Foo ( const Foo & ) = poista ; void bar ( int ) = poista ; tyhjä palkki ( kaksinkertainen ) {} }; // ... Foo obj ; obj . baari ( 5 ); // virhe! obj . bar ( 5,42 ); // okei Kirjoita long long int

Kokonaislukutyyppi long long inton määritelty C99 :ssä ja sitä käytetään laajalti de facto C++:ssa. Nyt se on virallisesti sisällytetty standardiin.

Staattinen diagnostiikka

C++11:llä on kaksi staattista diagnostiikkamekanismia:

  • Avainsana static_assertantaa käännösvirheen, jos suluissa oleva lauseke on epätosi.
  • Kirjasto type_traits, joka sisältää malleja, jotka tarjoavat tyyppitietoja käännöshetkellä.
#include <type_traits> malli < luokkaT > _ tyhjä ajo ( T * aData , koko_t n ) { static_assert ( std :: is_pod < T >:: arvo , "Tyypin T on oltava yksinkertainen." ); ... } Työskentely koko datajäsenten kanssa luokissa luomatta objektia

C++03 salli operaattorin sizeofkäytön yksinkertaisissa tyypeissä ja objekteissa. Mutta seuraava rakenne oli virheellinen:

struct SomeType { OtherType -jäsen ; }; sizeof ( SomeType :: jäsen ); //Ei toimi C++03:ssa, mutta totta C++11:ssä.

Tämän puhelun tuloksena tulisi olla koko OtherType. C++03 ei tue tällaista kutsua, eikä tätä koodia käännetä. C++11 sallii tällaiset konstruktit.

Objektien kohdistuksen ohjaus ja kohdistuspyynnöt

C++11 mahdollistaa muuttujien tasaamisen käyttämällä alignofja operaattoreita alignas.

alignofottaa tyypin ja palauttaa tavujen määrän, jolla objektia voidaan siirtää. Esimerkiksi struct X { int n; char c; };8 tavulle se alignofpalauttaa arvon 4. Linkkeille se palauttaa linkkityypin arvon; taulukoille taulukkoelementin arvo

alignasohjaa objektin kohdistusta muistissa. Voit esimerkiksi määrittää, että char-taulukon on oltava oikein kohdistettu tyypin tallentamiseksi float:

alignas ( float ) unsigned char c [ sizeof ( float )] Sallitaan toteutukset roskakeräimellä Attribuutit

Muutokset C++-standardikirjastoon

Muutoksia olemassa oleviin komponentteihin

  • Kun se liitetään, std::setohjelmoija tietää joskus, mihin kohtaan uusi elementti päätyy. Tätä varten käytetään valinnaista parametria - "vintti"; jos arvaus on oikea, aikaestimaatti on kuoletettu vakio, ei O(log n) . "Vihje":n merkitys C++11:ssä muuttui: aiemmin se tarkoitti nykyistä elementtiä , mikä ei ole täysin oikein: ei ole selvää, mitä tehdä, jos lisäys on ensimmäisessä paikassa. Nyt tämä on elementti nykyisen jälkeen .
  • Kätevä malli on kirjoitettu, joka kutsuu rakentajia ilman muistin varausta - std::allocator_traits<>::construct(). Kaikkiin säilöihin on lisätty menetelmä emplace, joka luo objektin paikalleen.
  • Lisätty uusia C++11-kieliominaisuuksia.
  • Lisätty menetelmiä cbeginja cendtaattu luoda const iteraattoreita. Kätevä metaohjelmointiin, tyyppien asettamiseen auto.
  • Säiliöissä, jotka aloittavat muistin marginaalilla, on ilmestynyt funktio shrink_to_fit.
  • B std::listasettaa tiukemmat rajoitukset sille, mitä tehdään O :ssa ( n ), ja mitä tehdään vakioajassa.
  • Lisätty std::vectorsuora pääsy muistiin data().
  • Estä useita std::stringviittaamasta samaan muistiin. Tämän ansiosta ilmestyi suora pääsy kautta front(), joka on kätevä esimerkiksi merkkijonon ja WinAPI :n vuorovaikutukseen .

Virtauksen ohjaus

Vaikka C++03-kieli tarjoaa muistimallin, joka tukee monisäikeistystä, pääasiallisen tuen monisäikeen käyttämiselle tarjoaa C++11-standardikirjasto.

Tarjolla on säikeen luokka ( std::thread), joka hyväksyy funktioobjektin (ja valinnaisen luettelon sille välitettävistä argumenteista) suoritettavaksi uudessa säikeessä. Voit pakottaa säikeen pysähtymään ennen kuin toinen suorittava säie on valmis tarjoamalla tukea säikeiden yhdistämiselle jäsentoiminnon kautta std::thread::join(). Jos mahdollista, pääsy säikeen alkuperäiseen kahvaan tarjotaan alustakohtaisia ​​toimintoja varten jäsentoiminnon kautta std::thread::native_handle().

Säikeiden välistä synkronointia varten kirjastoon lisätään sopivat mutexet ( std::mutexjne std::recursive_mutex.) ja ehtomuuttujat ( std::condition_variableja ). std::condition_variable_anyNe ovat saatavilla resurssien alustus (RAII) -lukkojen ( std::lock_guardja std::unique_lock) ja lukitusalgoritmien avulla käytön helpottamiseksi.

Tehokas matalan tason työ vaatii joskus viestinnän säikeiden välillä ilman mutexien ylimääräisiä kustannuksia. Tämä tehdään käyttämällä atomioperaatioita muistipaikoissa. Ne voivat valinnaisesti määrittää toiminnolle vaadittavat muistin näkyvyysrajat. Eksplisiittisiä muistiesteitä voidaan myös käyttää tähän tarkoitukseen.

C++11-säiekirjasto sisältää myös futuurit ja lupaukset asynkronisten tulosten välittämiseksi säikeiden välillä sekä luokan std::packaged_taskfunktiokutsun käärimiseen, joka voi tuottaa tällaisen asynkronisen tuloksen. Futuuriehdotusta on kritisoitu, koska siitä puuttuu tapa yhdistää futuureja ja tarkistaa yhden lupauksen toteutuminen lupaussarjassa.

Tulevaan C++ valkoiseen paperiin on sijoitettu lisää korkean tason langoituslaitteita, kuten lanka-altaita. Ne eivät ole osa C++11:tä, mutta niiden mahdollisen toteutuksen odotetaan rakennettavan kokonaan ketjutuskirjaston ominaisuuksien päälle.

Uusi toiminto std::asynctarjoaa kätevän tavan suorittaa tehtäviä ja sitoa niiden suorittamisen tulos std::future. Käyttäjä voi valita, suoritetaanko työ asynkronisesti erillisessä säikeessä vai synkronisesti nykyisessä säikeessä, joka odottaa arvoa.

Hash-taulukot

std::hash_setja std::hash_mapovat pitkään olleet epästandardi STL-laajennus, itse asiassa toteutettu useimmissa kääntäjissä. C++11:ssä niistä tuli vakio, nimillä std::unordered_setja std::unordered_map. Vaikka ne ovat itse asiassa hash-taulukoita ja standardi ei jätä paljon heiluttelutilaa, nimet annetaan C++-tyyliin: ei "miten ne on toteutettu", vaan "mitä ne ovat".

Säännölliset lausekkeet

Uusi kirjasto, joka on ilmoitettu otsikkotiedostossa <regex>, sisältää useita uusia luokkia:

Toimintoa std::regex_searchkäytetään etsimiseen, 'etsi ja korvaa' -toiminnossa käytetään toimintoa std::regex_replace. Funktio palauttaa merkkijonon korvauksen suorittamisen jälkeen. Algoritmit std::regex_searchja std::regex_replaceottavat syötteenä säännöllisen lausekkeen ja merkkijonon ja palauttavat löydetyt tulokset esiintymänä std::match_results.

Käyttöesimerkki std::match_results:

const char * reg_esp = "[ ,. \\ t \\ n;:]" ; // Erotinmerkkien luettelo. // sama voidaan tehdä käyttämällä "raakoja" merkkijonoja: // const char *reg_esp = R"([ ,.\t\n;:])"; std :: regex rgx ( reg_esp ); // 'regex' on esiintymä malliluokasta // 'basic_regex' malliparametrilla 'char'. std :: cmatch match ; // 'cmatch' on esiintymä malliluokasta // 'match_results' malliparametrilla 'const char *'. const char * target = "Näkemätön yliopisto - Ankh-Morpork" ; // Korjaa kaikki sanat merkkijonosta "target", jotka on erotettu merkillä "reg_esp". if ( std :: regex_search ( kohde , vastaavuus , rgx ) ) { // Jos annetuilla merkeillä erotetut sanat ovat merkkijonossa. const koko_t n = vastaa . koko (); for ( koko_t a = 0 ; a < n ; a ++ ) { std :: string str ( vastaa [ a ]. ensimmäinen , vastaa [ a ]. toinen ); std :: cout << str << " \n " ; } }

Huomaa, että kaksinkertaiset kenoviivat ovat pakollisia, koska C++ käyttää kenoviivaa välttääkseen merkkejä. Voit käyttää "raakoja merkkijonoja" - toinen C++11-standardin innovaatio.

Kirjasto <regex>ei vaadi muutoksia olemassa oleviin otsikkotiedostoihin eikä lisäkielilaajennusten asentamista.


Extendable Random Number Generation Classes

C-standardikirjasto salli pseudosatunnaislukujen luomisen käyttämällä rand. Sen käyttäytyminen voi kuitenkin vaihdella toteutuksesta riippuen.

Tämä toiminnallisuus on jaettu kahteen osaan: generaattorimoottoriin, joka sisältää satunnaislukugeneraattorin nykyisen tilan ja tuottaa näennäissatunnaisia ​​lukuja, ja jakaumaan, joka määrittää tuloksen alueen ja matemaattisen jakauman . Näiden kahden objektin yhdistelmä luo satunnaislukugeneraattorin.

Generaattorimoottorit:

Jakelut:

Esimerkki:

#sisällytä <satunnainen> #sisällytä <toiminnallinen> std :: yhtenäinen_int_jakauma < int > jakelu ( 0 , 99 ); std :: mt19937moottori ; _ // Mersenne vortex MT19937 auto generator = std :: bind ( jakelu , moottori ); int satunnainen = generaattori (); // Hanki satunnaisluku väliltä 0 - 99. int random2 = jakauma ( moottori ); // Hanki satunnaisluku käyttämällä moottoria ja jakelua suoraan.



Suunnitellut ominaisuudet eivät sisälly standardiin

Moduulit Otsikkotiedostojen valtava määrä johti neliölliseen pidentymiseen käännösajassa: sekä koodin määrä että moduulien määrä yhdessä käännösyksikössä lisääntyvät. Moduulien tulee tarjota samanlainen mekanismi kuin Delphi DCU - tiedostot tai Java - luokkatiedostot .

Poistetut tai vanhentuneet ominaisuudet

Katso myös

Muistiinpanot

  1. Herb Sutter , Meillä on kansainvälinen standardi: C++0x on yksimielisesti hyväksytty Arkistoitu 11. joulukuuta 2018 Wayback Machinessa
  2. Scott Meyers , Yhteenveto C++11-ominaisuuden saatavuudesta gcc:ssä ja MSVC :ssä Arkistoitu 26. lokakuuta 2011 Wayback Machinessa , 16. elokuuta 2011
  3. ISO , ISO/IEC 14882:2011 Arkistoitu 29. tammikuuta 2013 Wayback Machinessa
  4. C++0x-nimi määritelty lopullisessa luonnoksessa N3290 . Arkistoitu 20. kesäkuuta 2010 Wayback Machinessa
  5. Stroustrup, Bjorn  - C++0x - seuraava ISO C++ -standardi Arkistoitu 11. toukokuuta 2011 Wayback Machinessa
  6. C++ Standards Committee Papers . Haettu 24. helmikuuta 2008. Arkistoitu alkuperäisestä 18. maaliskuuta 2010.
  7. C++-lähde Bjarne Stroustrup ( 2. tammikuuta 2006 ) Lyhyt katsaus C++0x:ään . (Englanti)

C++-standardikomitean asiakirjat

  •   Asiakirja nro. 1401: Jan Kristoffersen (21. lokakuuta 2002)Atomioperaatiot monisäikeisissä ympäristöissä
  •   Asiakirja nro. 1402: Doug Gregor (22. lokakuuta 2002)Ehdotus polymorfisen funktion objektikääreen lisäämiseksi standardikirjastoon
  •   Asiakirja nro. 1403: Doug Gregor (8. marraskuuta 2002)Ehdotus monikkotyyppien lisäämiseksi vakiokirjastoon
  •   Asiakirja nro. 1424: John Maddock (3. maaliskuuta 2003)Ehdotus tyyppiominaisuuksien lisäämiseksi standardikirjastoon
  •   Asiakirja nro. 1429: John Maddock (3. maaliskuuta 2003)Ehdotus säännöllisen lausekkeen lisäämiseksi standardikirjastoon
  •   Asiakirja nro. 1449: B. Stroustrup, G. Dos Reis, Mat Marcus, Walter E. Brown, Herb Sutter (7. huhtikuuta 2003)Ehdotus mallialiaksien lisäämiseksi C++:aan
  •   Asiakirja nro. 1450: P. Dimov, B. Dawes, G. Colvin (27. maaliskuuta 2003)Ehdotus yleiskäyttöisten älykkäiden osoittimien lisäämiseksi kirjaston tekniseen raporttiin (versio 1)
  •   Asiakirja nro. 1452: Jens Maurer (10. huhtikuuta 2003)Ehdotus laajennettavan satunnaislukujärjestelmän lisäämiseksi vakiokirjastoon (versio 2)
  •   Asiakirja nro. 1453: D. Gregor, P. Dimov (9. huhtikuuta 2003)Ehdotus viitekääreen lisäämiseksi vakiokirjastoon (versio 1)
  •   Asiakirja nro. 1454: Douglas Gregor, P. Dimov (9. huhtikuuta 2003)Yhtenäinen menetelmä funktioobjektien palautustyyppien laskemiseen (versio 1)
  •   Asiakirja nro. 1456: Matthew Austern (9. huhtikuuta 2003)Ehdotus hash-taulukoiden lisäämiseksi vakiokirjastoon (versio 4)
  •   Asiakirja nro. 1471: Daveed Vandevoorde (18. huhtikuuta 2003)Heijastava metaohjelmointi C++:ssa
  •   Asiakirja nro. 1676: Bronek Kozicki (9. syyskuuta 2004)Ei-jäsen ylikuormitettu kopiointitoimeksianto
  •   Asiakirja nro. 1704: Douglas Gregor, Jaakko Järvi, Gary Powell (10. syyskuuta 2004)Variadic Templates: Exploring the Design Space
  •   Asiakirja nro. 1705: J. Järvi, B. Stroustrup, D. Gregor, J. Siek, G. Dos Reis (12. syyskuuta 2004)Decltype (ja auto)
  •   Asiakirja nro. 1717: Francis Glassborow, Lois Goldthwaite (5. marraskuuta 2004)selkeät luokka- ja oletusmääritykset
  •   Asiakirja nro. 1719: Herb Sutter, David E. Miller (21. lokakuuta 2004)Voimakkaasti kirjoitetut enumit (versio 1)
  •   Asiakirja nro. 1720: R. Klarer, J. Maddock, B. Dawes, H. Hinnant (20. lokakuuta 2004)Ehdotus staattisten väitteiden lisäämiseksi ydinkieleen (versio 3)
  •   Asiakirja nro. 1757: Daveed Vandevoorde (14. tammikuuta 2005)Oikeat kulmasulut (versio 2)
  •   Asiakirja nro. 1811: J. Stephen Adamczyk (29. huhtikuuta 2005)Pitkän pitkän tyypin lisääminen C++:aan (versio 3)
  •   Asiakirja nro. 1815: Lawrence Crowl (2. toukokuuta 2005)ISO C++ Strategic Plan for Multithreading
  •   Asiakirja nro. 1827: Chris Uzdavinis, Alisdair Meredith (29. elokuuta 2005)Explicit Override Syntax for C++
  •   Asiakirja nro. 1834: Detlef Vollmann (24. kesäkuuta 2005)pyyntö kohtuullisesta rinnakkaiskäsittelyn tuesta C++:ssa
  •   Asiakirja nro. 1836: ISO/IEC DTR 19768 (24. kesäkuuta 2005)Luonnos tekniseksi raportiksi C++-kirjaston laajennuksista
  •   Asiakirja nro. 1886: Gabriel Dos Reis, Bjarne Stroustrup (20. lokakuuta 2005)C++-käsitteiden määrittäminen
  •   Asiakirja nro. 1891: Walter E. Brown (18. lokakuuta 2005)Edistyminen kohti opaque Typedefs for C++0X
  •   Asiakirja nro. 1898: Michel Michaud, Michael Wong (6. lokakuuta 2004)Huolinta ja perineet rakentajat
  •   Asiakirja nro. 1919: Bjarne Stroustrup, Gabriel Dos Reis (11. joulukuuta 2005)Alustuslistat
  •   Asiakirja nro. 1968: V Samko J Willcock, J Järvi, D Gregor, A Lumsdaine (26. helmikuuta 2006)Lambda-ilmaisut ja sulkemiset C++:lle
  •   Asiakirja nro. 1986: Herb Sutter, Francis Glassborow (6. huhtikuuta 2006)Rakentajien valtuuttaminen (versio 3)
  •   Asiakirja nro. 2016: Hans Boehm, Nick Maclaren (21. huhtikuuta 2002)Pitäisikö haihtuvien hankkia atomisuuden ja säikeen näkyvyyden semantiikka?
  •   Asiakirja nro. 2142: ISO/IEC DTR 19768 (12. tammikuuta 2007)State of C++ Evolution (Portlandin ja Oxfordin 2007 kokousten välillä)
  •   Asiakirja nro. 2228: ISO/IEC DTR 19768 (3. toukokuuta 2007)State of C++ Evolution (Oxford 2007 Meetings)
  •   Asiakirja nro. 2258: G. Dos Reis ja B. StroustrupTemplates aliakset
  •   Asiakirja nro. 2280: Lawrence Crowl (2. toukokuuta 2007)Thread-Local Storage
  •   Asiakirja nro. 2291: ISO/IEC DTR 19768 (25. kesäkuuta 2007)C++ Evolution -tilanne (Toronto 2007 -kokoukset)
  •   Asiakirja nro. 2336: ISO/IEC DTR 19768 (29. heinäkuuta 2007)C++ Evolution -tilanne (Toronto 2007 -kokoukset)
  •   Asiakirja nro. 2389: ISO/IEC DTR 19768 (7. elokuuta 2007)C++ Evolutionin tila (Konaa 2007 edeltävät kokoukset)
  •   Asiakirja nro. 2431: SC22/WG21/N2431 = J16/07-0301 (2. lokakuuta 2007),Nollaosoittimen nimi: nullptr
  •   Asiakirja nro. 2432: ISO/IEC DTR 19768 (23. lokakuuta 2007)C++ Evolution -tilanne (Kona 2007 -kokouksen jälkeinen)
  •   Asiakirja nro. 2437: Lois Goldthwaite (5. lokakuuta 2007)Eksplisiittiset muunnosoperaattorit
  •   Asiakirja nro. 2461: ISO/IEC DTR 19768 (22. lokakuuta 2007)työluonnos, ohjelmointikielen standardi C++
  •   Asiakirja nro. 2507: ISO/IEC DTR 19768 (4. helmikuuta 2008)C++ Evolutionin tila (pre-Bellevue 2008 -kokous)
  •   Asiakirja nro. 2544: Alan Talbot, Lois Goldthwaite, Lawrence Crowl, Jens Maurer (29. helmikuuta 2008)Rajoittamattomat ammattiliitot
  •   Asiakirja nro. 2565: ISO/IEC DTR 19768 (7. maaliskuuta 2008)C++ Evolution -tila (Bellevue 2008 -kokouksen jälkeinen)
  •   Asiakirja nro. 2597: ISO/IEC DTR 19768 (29. huhtikuuta 2008)C++ Evolution -tilanne (Pre-Antipolis 2008 -kokous)
  •   Asiakirja nro. 2606: ISO/IEC DTR 19768 (19. toukokuuta 2008)työluonnos, ohjelmointikielen C++ standardi
  •   Asiakirja nro. 2697: ISO/IEC DTR 19768 (15.6.2008)WG21-kokouksen pöytäkirja 8.-15.6.2008
  •   Asiakirja nro. 2798: ISO/IEC DTR 19768 (4. lokakuuta 2008)työluonnos, ohjelmointikielen C++ standardi
  •   Asiakirja nro. 2857: ISO/IEC DTR 19768 (23. maaliskuuta 2009)työluonnos, ohjelmointikielen C++ standardi
  •   Asiakirja nro. 2869: ISO/IEC DTR 19768 (28. huhtikuuta 2009)C++ Evolution -tila (San Franciscon 2008 kokouksen jälkeinen)
  •   Asiakirja nro. 3000: ISO/ISC DTR 19769 (9. marraskuuta 2009) työluonnos, ohjelmointikielen C++ standardi
  •   Asiakirja nro. 3014: Stephen D. Clamage (4. marraskuuta 2009)AGENDA, PL22.16 Kokous nro. 53, WG21-kokous nro. 48, 8.-13. maaliskuuta 2010, Pittsburgh, PA
  •   Asiakirja nro. 3082: Herb Sutter (13. maaliskuuta 2010)C++0x kokousaikataulu
  •   Asiakirja nro. 3092: ISO/ISC DTR 19769 (26. maaliskuuta 2010) työluonnos, ohjelmointikielen C++ standardi
  •   Asiakirja nro. 3126: ISO/ISC DTR 19769 (21. elokuuta 2010) työluonnos, ohjelmointikielen C++ standardi
  •   Asiakirja nro. 3225: ISO/ISC DTR 19769 (27. marraskuuta 2010) työluonnos, ohjelmointikielen C++ standardi
  •   Asiakirja nro. 3242: ISO/ISC DTR 19769 (28. helmikuuta 2011) työluonnos, ohjelmointikielen C++ standardi
  •   Asiakirja nro. 3291: ISO/ISC DTR 19769 (5. huhtikuuta 2011) työluonnos, ohjelmointikielen C++ standardi
  •   Asiakirja nro. 3290: ISO/ISC DTR 19769 (5. huhtikuuta 2011)FDIS, ohjelmointikielen standardi C++
  •   Asiakirja nro. 3337 : Päivämäärä: 2012-01-16 Työluonnos, ohjelmointikielen standardi C++

Linkit

Kirjallisuus

  • Stanley B. Lippman, Josy Lajoye, Barbara E. Moo. C++ ohjelmointikieli. Core Course 5th Edition = C++ Primer (5th Edition). - M. : "Williams" , 2014. - 1120 s. - ISBN 978-5-8459-1839-0 .
  • Siddhartha Rao. Opettele itsesi C++ 21 päivässä, 7. painos = Sams Teach Yourself C++ in One Hour a Day, 7. painos. - M. : "Williams" , 2013. - 688 s. — ISBN 978-5-8459-1825-3 .
  • Stephen Prata. C++ ohjelmointikieli (C++11). Luennot ja harjoitukset, 6. painos = C++ Primer Plus, 6. painos (Developer's Library). - M. : "Williams" , 2012. - 1248 s. - ISBN 978-5-8459-1778-2 .