Az új szabvány egy fontos pontban módosítja a C++ szintaxisát. A régi
C++-ban a >>
karaktersorozat minden esetben a shift
right
operátort jelentette, így sablonok használatakor szóközt
kellett közéjük tenni. Az új szabvány szerint azonban sablonok használatakor
ez a jelentése élvez elsőbbséget. Ezt a viselkedést zárójelezéssel lehet
megváltoztatni. A következő példában a hibás sorban a SomeType<1>-et
fogja a fordító típusnak értelmezni, a harmadik sor mutatja a példányosítást
helyesen.
A standard C++-ban kétféle string literált használhattunk ezelőtt.
Az új C++-ban három unicode kódolás támogatása is megtalálható, használhatóak UTF-8, UTF-16 illetve UTF-32 kódolású sztring
literálok is. Ezek típusa rendre const char[]
,
const char16_t[]
, const char32_t[]
. A következőképpen hozhatóak
létre:
A literálokba Unicode karaktereket is tudunk rakni, 16 bites kódolásban
\u
, 32 bites kódolásban \U
előtaggal:
Új hasznos funkció a raw
literál. Raw literálban használhatjuk a
" jelet is, a literál kezdetét R"DELIMITER[, végét
]DELIMITER" karaktersorozattal jelezhetjük.
Az új C++ nyelvben lehet literált definiálni. Az új literált az utótagja alapján lehet azonosítani (amely kötelezően aláhúzás jellel kezdődik), továbbá definiálni kell egy operátort:
Ez természetesen működik az új sztring literálokkal is:
A régi C++-ban azon objektumoknak, amiknek nem volt meghatározva, a fordító meghatározott bizonyos funkciókat, mint például default constructor, copy constructor, destructor. Ezeket a felhasználó felüldefiniálhatta. Ezen kívül volt lehetőség néhány globális operátor (pl operator=, vagy a new operátor) felüldefiniálására is.
Viszont ezen kívül más lehetősége nincs a programozónak, és ez igen kevés befolyást jelent ezen funkciók felett. Az új szabvány lehetőséget biztosít, hogy explicit módon használja, vagy megtiltsa ezeket a funkciókat.
Például megadhatjuk a default constructort explicit módon a következőképpen:
Ezen kívül lehetőség van direkt módon megtiltani egyes funkciókat:
Nézzük meg a következő példát
A fenti strukturában az f függvény meghívása double típussal el lesz utasítva a fordító által, ahelyett, hogy automatikusan int-é konvertálódna. A fenti példa általánosítását láthatjuk a következő példában, ahol egy függvény hívását megtiltjuk minden egyes típusra, kivéve az int-re.
A static assert a következőképpen néz ki:
A fordító kiértékeli a kifejezést (expression), és kiírja a string üzenetet, ha a kiértékelés eredménye hamis. (assertion failed) Például:
A régi C++-ban csupán statikus, konstans egész típusú adattagok inicializálhatóak az osztályon belül, méghozzá konstans kifejezéssel. Vagyis:
Ennek alapján az alapötlet a C++0x-ben az, hogy engedélyezzék a nem statikus adattagok ilyen módon történő inicializálását is.
Ez a következővel ekvivalens:
Ezzel megspórolhatunk egy csomó gépelést, de az igazi előnyük akkor látszik, amikor olyan osztályokat tekintünk, amelyek több konstruktorral rendelkeznek. Nézzük a következő példát:
Az új szabvány lehetőséget ad arra, hogy az előző példát átírjuk a következőre:
Amikor egy adattag egy konstruktorral és egy inicializálóvfüggvénnyel is inicializálva van, akkor csak a konstruktoré lesz érvényes, szóval írhatjuk akár a következőt is:
A régi C++-ban nem konstans referenciákat lehetett balértékekhez (lvalue) kötni, konstansokat pedig bal-, és jobbértékekhez egyaránt. Viszont nem volt semmi, amit hozzá lehetett kapcsolni egy nem konstans jobbértékhez. Tekintsük a következő példát:
Ha incr(0) engedélyezve lenne, akkor egyrészt egy senki által nem használt temporáris változó meg lenne növelve eggyel, és ami sokkal rosszabb, ezentúl 0 értéke 1 lenne. Ez elsőre furcsán hangzik, de volt egy hasonló bug a korai Fortran fordítókban. Ezekután tekintsük a következő cserélőfüggvényt
Ha T típus valami bonyolult típus, akkor a fenti swap függvény egy elég költséges függvény lehet. Sőt, igazából nekünk egyáltalán nincs szükségünk egyetlen másolatra sem, mi csak egyszerűen mozgatgatni akarjuk egy kicsit az a, b, és tmp változókat.
Az új szabvány lehetőséget ad arra, hogy úgynevezett "move constructor"-t, illetve "move assignment"-et definiáljunk, hogy az egyes elemeket másolás helyett mozgassunk.
A fenti példában látható && jelöli az úgynevezett rvalue referenciákat. Ezeket mind bal-, mind jobbértékekhez hozzáköthetjük.
A példához hasonlóan pl s1=s2 esetében használni a move assignment-et lényegében azt jelenti, hogy nem csinálunk egy egy másolatot s2 karaktereiből, hanem ehelyett hagyjuk, hogy s1 a sajátjaiként kezelje azokat, és valahogy töröljük s1 régi karaktereit.
Tekintsük a következő példát:
move(x) jelentése: "úgy használhatod x-et, mintha jobbérték lenne".
A régi void swap(T& a, T& b) továbbra is balértékeket használ, de most, a C++0x lehetőséget ad számunkra a következőkre:
A fenti kóddal felcserélhetünk egy balértéket, és egy jobbértéket.
A C++ korai változatában egy olyan adattag, amely konstruktorral, destruktorral, vagy értékadással rendelkezett, nem lehetett unió tagja.
Ezek után
Az új C++0x szabvány megváltoztatja a korlátozásokat.
Például:
Hibásnak tűnhet, de az új korlátozások segítenek.
Vagyis U2 használhatatlan, hacsak be nincs ágyazva egy struct-ba, ami képes figyelni, melyik adattag van használva. Vagyis: