Sie sind auf Seite 1von 67

TTH BERTALAN

A C++11 NYELV
J LEHETSGEINEK
TTEKINTSE

Tth Bertalan:

A C++11 nyelv j lehetsgeinek ttekintse

2013

Jelen dokumentumra a Creative Commons Nevezd meg! Ne add el! Ne


vltoztasd meg! 3.0 Unported licensz felttelei rvnyesek: a mvet a felhasznl msolhatja, tbbszrzheti, tovbbadhatja, amennyiben feltnteti
a szerz nevt s a m cmt, de nem mdosthatja, s kereskedelmi forgalomba se hozhatja.

Lektorlta: Juhsz Tibor

Tth Bertalan, 2013

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse

Tartalom
Bevezets ............................................................................................................................................ 5
Nhny hasznos hivatkozs................................................................................................................. 5
1 Vltozsok a C++ nyelv alapelemei szintjn ..................................................................................... 6
1.1 j, illetve mdostott rtelm C++ kulcsszavak ........................................................................ 6
1.2 j egsz tpusok......................................................................................................................... 6
1.3 j lebegpontos rtkek ........................................................................................................... 7
1.4 Szigoran tpusos felsorolsok enum osztlyok ..................................................................... 7
1.5 A nullptr s a nullptr_t .............................................................................................................. 8
1.6 Sztring literlok.......................................................................................................................... 8
1.6.1 Nyers (raw) sztring literlok ............................................................................................... 8
1.7 Felhasznl ltal definilt literlok............................................................................................ 9
1.8 Fordts idej konstans kifejezsek (constexpr) ....................................................................... 9
1.8.1 A static_assert kulcssz .................................................................................................... 10
1.9 Kivtelek tovbbtsnak tiltsa (noexcept) ........................................................................... 10
1.10 Vltozk memriahatrra igaztsa ...................................................................................... 11
2 j, szokatlan nyelvi megoldsok .................................................................................................... 12
2.1 Automatikus tpus-meghatrozs ........................................................................................... 12
2.2 Jobbrtk hivatkozsok (&&) .................................................................................................. 13
2.3 Adatok thelyezse (forward s a move) ................................................................................ 14
2.4 Okos (smart) mutatk .......................................................................................................... 15
2.5 Egysges inicializls ............................................................................................................... 17
2.6 Tartomnyalap for ciklus, a begin s az end hvsok ............................................................ 18
2.7 - lambda kifejezsek (fggvnyek) ....................................................................................... 20
2.8 Programkd prhuzamos futtatsa......................................................................................... 22
2.8.1 Aszinkron kdvgrehajts ................................................................................................ 23
2.8.2 Szlak futtatsa ................................................................................................................ 24
2.8.3 Szlak szinkronizlsa kizrssal ...................................................................................... 26
2.8.4 Szlak szinkronizlsa atomi vltozkkal ......................................................................... 27
3. Vltozsok az osztlyok s a sablonok krben ............................................................................ 29
3.1 Konstruktorok deleglsa, adattagok inicializlsa, sizeof adattagra ..................................... 29
3.2 Opertorfggvnyek explicit tpus-talaktssal ..................................................................... 30
3.3 Az override s a final mdostk ............................................................................................. 30
3.4 A delete s a default tagfgvnyek ......................................................................................... 32
3.5 Korltozsok nlkli union tpus ............................................................................................. 32
3.6 Sablonok s a C++11 ................................................................................................................ 33
3.6.1 Szintaxis ............................................................................................................................ 33
3.6.2 Kls sablonok.................................................................................................................. 33
3.6.3 Sablon lnevek (template alias) ....................................................................................... 34
3.6.4 Sablonok vltoz hosszsg argumentumlistval (variadic templates)......................... 35
3.6.5 Htravetett visszatrsi tpus (suffix return types) .......................................................... 37
4. A C++11 knyvtr jdonsgai ........................................................................................................ 38
4.1 j fggvnyek s tagfggvnyek a C++ knyvtrban .............................................................. 38
4.1.1 C-sztring tartalmnak szmm alaktsa .......................................................................... 38
4.1.2 A string tpus s a numerikus adatok kztti talaktsok ............................................. 39
4.1.3 Unicode karakterek s sztringek talaktsa .................................................................... 39
4.1.4 j matematikai fggvnyek.............................................................................................. 40
4.1.5 A bvtett complex osztlysablon .................................................................................... 41
4.1.6 Fordts idej racionlis aritmetika .................................................................................. 41
4.2 Vletlen szmok ellltsa ..................................................................................................... 43

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


4.3 Id- s dtumkezels ............................................................................................................... 44
4.4 Regulris kifejezsek knyvtra............................................................................................... 46
4.5 Kibvtett tpuskezel knyvtr ............................................................................................... 48
4.6 Polimorf fggvnyobjektumok ................................................................................................ 49
4.7 Inicializl lista sajt osztlyokban .......................................................................................... 51
4.8 Vltozsok a kontnerek (trolk) knyvtrban ................................................................... 53
4.8.1 Kezdrtkads a kontnereknek .................................................................................... 56
4.8.2 A move szemantika s az STL kontnerek ........................................................................ 56
4.8.3 A begin, end s swap fggvnysablonok hasznlata ........................................................ 58
4.9 Kibvtett algoritmus knyvtr ................................................................................................ 59
4.10 Rekordok j megkzeltsben (tuple).................................................................................... 62
4.11 A szabvnyos C++ nyelv deklarcis llomnyai ................................................................... 63

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse

A C++11 nyelv j lehetsgeinek ttekintse


Bevezets
A C++11 (ISO/IEC 14882:2011) a C++ programozsi nyelv 2011 szeptemberben megjelent szabvnya,
amely egy modern, az eddigieknl is hatkonyabb programozsi nyelvet ad a programozk kezbe. A
nyelv 2003-as vltozata elssorban hibajavts volt az eredetileg 1998-as szabvnyhoz kpest, a mostani azonban egy sor jdonsgot is tartalmaz. sszefoglalnkban csak az j elemeket mutatjuk be,
felttelezve az eredeti C++ nyelv ismerett. A szabvnyostsi folyamat ezzel nem zrult le, mr ismert a C++14 s a C++17 szabvnyokban bevezetsre kerl nyelvi megoldsok egy rsze.
Az sszefoglalban a jobb ttekinthetsg rdekben nknyesen csoportostottuk a C++11 nyelv j
lehetsgeit. Ennek sorn az alapvet nyelvi elemektl, a sablonok hasznlatn t jutunk el a Szabvnyos Sablonknyvtr (STL) alkalmazsig.

Nhny hasznos hivatkozs


Sajnos napjainkban mg egyik C++ fordt sem tmogatja teljes mrtkben az j szabvny ajnlsait.
Mivel a tmogatott megoldsok kre naprl-napra, verzirl-verzira bvl, az Interneten rdemes
utna nzni, hogy az ltalunk hasznlt fordtprogrammal, mit hasznlhatunk az sszefoglalban
bemutatott, s a nem ismertetett nyelvi elemek kzl.
Nhny hasznos hivatkozs:
C++ 11 szabvny
http://isocpp.org/std/the-standard
C11 szabvny
http://www.open-std.org/jtc1/sc22/wg14/
C/C++ referencia
http://en.cppreference.com/w/cpp
C/C++ referencia
http://www.cplusplus.com/reference/
C++11 Wikipedia
http://en.wikipedia.org/wiki/C++11
C11 Wikipedia
http://en.wikipedia.org/wiki/C11_(C_standard_revision)
C++11 jellegzetessgek a Visual Studio 2012-ben (Microsoft Development Network)
http://msdn.microsoft.com/en-us/library/vstudio/hh567368.aspx
C++0x/C++11 tmogats a GCC-ben
http://gcc.gnu.org/projects/cxx0x.html

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse

1 Vltozsok a C++ nyelv alapelemei szintjn


Ebben rszben ttekintjk a C++11 nyelv j alaptpusait s konstansmegadsi mdjait:
j, illetve mdostott rtelm C++ kulcsszavak,
j egsz tpusok,
j lebegpontos rtkek,
szigoran tpusos felsorolsok enum osztlyok,
a nullptr s a nullptr_t,
sztring literlok,
felhasznl ltal definilt literlok,
fordts idej konstans kifejezsek (constexpr), a static_assert kulcssz,
kivtelek tovbbtsnak tiltsa (noexcept),
vltozk memriahatrra igaztsa.
1.1 j, illetve mdostott rtelm C++ kulcsszavak
j foglalt szavak
alignas
alignof
char16_t
char32_t
constexpr
decltype
final
noexcept
nullptr
override
static_assert
thread_local

Mdostott kulcsszavak
auto
default
delete
export
using

1.2 j egsz tpusok


A C++ szabvny most mr hivatalosan is tmogatja a long long s az unnsigned long long tpus egszeket, amelyek legalbb 64 biten troldnak. Minden egszekre vonatkoz mvelet elvgezhet
velk, s a C++ knyvtri elemei is segtik a hasznlatukat. Konstans rtkekben az ll, LL, illetve az ull,
ULL uttaggal jellhetjk ket. A tpusok rtkhatrait hagyomnyosan a <climits> fejllomny
(LLONG_MIN, LLONG_MAX, ULLONG_MIN, ULLONG_MAX), s a <limits> fjlban definilt
numeric_limits<tpus> osztlysablon adattagjai biztostjk szmunkra.
int main() {
long long int x=123456789012345678LL;
long long z = 0LL;
unsigned long long y = x / 712ULL;
cout << "y = " << y << endl;
cout << "z = ";
cin >> z;
cout << "z^2 = " << z*z << endl;
}

Platformfggetlen, rgztett mret egsz tpusokat, s az rtkhatrokat trol makrkat tallunk a


<cstdint> fejllomnyban, melyek kzl a leggyakrabban hasznltak:
int8_t
uint8_t
int16_t
uint16_t

signed char
unsigned char
short
unsigned short

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


int32_t
uint32_t
int64_t
uint64_t

int
unsigned
long long
unsigned long long

Az rtkhatr makrk INTn_MIN, INTn_MAX, UINTn_MIN, UINTn_MAX, ahol n rtke 8,16, 32 vagy
64 lehet.
1.3 j lebegpontos rtkek
A C++11 szabvny a float, double s a long double lebegpontos tpusok krt nem bvti, azonban a
lebegpontos rtkek terleten j eszkzket knl a programozk szmra. Egyrszt lehetsget
biztost a vgtelen (INFINITY) s a nem szm (NAN) rtkek kezelsre. Msrszt pedig a lebegpontos konstans rtkeket pontosabban adhatjuk meg hexadecimlis formban (a mantisszt 16-os,
mg a p/P bet utn a 2 kitevjt 10-es szmrendszerben kell szerepeltetnnk.) Pldul, a 0x1.004p7
decimlis rtke 128.125, a 0x1Ab2P2 konstans pedig 27336.
#include <iostream>
#include <cmath>
using namespace std;
int main() {
cout << 0x1.ap+0f << endl;
cout << 0x1.0P+10 << endl;
cout << 0x0.C90FDAA22168CP2 << endl;
cout << "1/0.0 = " << 1/0.0 << endl;
cout << "-1/0.0 = " << -1/0.0 << endl;
cout << "0.0/0.0 = " << 0.0/0.0 << endl;
cout << "sqrt(-1.0) = " << sqrt(-1.0) << endl;
cout << "INFINITY/INFINITY = " << INFINITY/INFINITY << endl;
}

A program futsnak eredmnye:

1.625
1024
3.14159
1/0.0 = inf
-1/0.0 = -inf
0.0/0.0 = nan
sqrt(-1.0) = nan
INFINITY/INFINITY = nan

1.4 Szigoran tpusos felsorolsok enum osztlyok


A felsorols osztlyok hasznlatval minden enum nll tpusknt jelenik meg, melynek tagjait az
enum nevvel s a hatkr opertorral minstve rhetjk el:
enum class Szin {FEKETE=0, KEK, ZOLD, PIROS=4};
int main() {
Szin alap = Szin::FEKETE;
if (Szin::PIROS == alap) {
}
alap = Szin(2);
cout << int(alap) << endl; // 2
}

Tovbbi lehetsg a felsorols elemtpusnak megadsa:


enum class Szin : char {FEKETE=0, KEK, ZOLD, PIROS=4};

Az elemek tpusaknt tetszleges eljeles vagy eljel nlkli egsz tpust szerepeltethetnk.

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


1.5 A nullptr s a nullptr_t
Hagyomnyosan a mutatk inicializlsra a 0 vagy a NULL rtkeket hasznltuk. A C++11 egyrtelmv teszi ezt az llapotot a nullptr kulcssz bevezetsvel. A nullptr rtk tpusa a nullptr_t tpus.
1.6 Sztring literlok
Ez idig ktfle sztring konstans hasznlhattunk a szabvnyos C++ nyelvben:

Az els a szoksos " " kztti szveg, ami const char tmbknt troldik, 0-s bjttal a vgn.
A msodik az L"..." jellssel hasznlhat,melynek eredmnyeknt egy const wchar_t tmb
jn ltre, 0 rtk utols elemmel. (Emlkeztetl a wchar_t a szles karakterek tpusa.)
A szles sztringekben hagyomnyos, rgztett 16 bit kdolssal trolhatunk Unicode szveget, azonban nem alkalmasak nagyobb kdmret szvegek trolsra.
A C++11-ben hrom jabb Unicode kdols tmogatsa is megtallhat: UTF-8, UTF-16 s UTF-32. Az
UTF-32 a karakter kdjt mindig 32 biten trolja, mg az UTF-16 1 vagy 2 egysget, az UTF-8 pedig 1-4
egysget hasznl erre a clra.
A C++ programokban a karakterkdolssal sszefgg kaotikus llapotok valamelyest cskkentek,
azonban a felhasznls tovbbi kvnnivalkat hagy maga utn. Az albbi tblzatban foglaltuk ssze
a lehetsgeket:
karakter tpus karakter konstans
norml karakterek
szles karakterek
UTF-8 kdols
UTF-16 kdols
UTF-32 kdols

char
wchar_t
char
char16_t
char32_t

'A', '\x41'
L'A', L'\x0041'
u'A', u'\u0041'
U'A', U'\U00000041'

sztring tpus
string
wstring
string
u16string
u32string

A
(violinkulcs: U+1D11E) s a (pi: U+03C0) jelet tartalmaz szvegek trolsa karakter tmbkben:
wchar_t cpw[] = L"violinkulcs : \U0001D11E, pi: \u03C0";
char cpu8[] = u8"violinkulcs : \U0001D11E, pi: \u03C0";
char16_t cpu16[] = u"violinkulcs : \U0001D11E, pi: \u03C0";
char32_t cpu32[] = U"violinkulcs : \U0001D11E, pi: \u03C0";

s sztring tpusokban:
wstring sw = L"violinkulcs : \U0001D11E, pi: \u03C0";
string s8 = u8"violinkulcs : \U0001D11E, pi: \u03C0";
u16string s16 = u"violinkulcs : \U0001D11E, pi: \u03C0";
u32string s32 = U"violinkulcs : \U0001D11E, pi: \u03C0";

A klnbz kdols karaktersorozatok kztti talaktsokhoz hasznlhatjuk a <locale> fejllomny


wstring_convert<> valamint a <codecvt> include fjl codecvt_utf8<>, codecvt_utf16<> s
codecvt_utf8_utf16<> osztlysablonjait.
1.6.1 Nyers (raw) sztring literlok
A hagyomnyos s a raw sztring literlok kztti alapvet klnbsg, hogy az utbbiban az ESCszekvencikat nem dolgozza fel fordt.
int main() {
setlocale(LC_ALL,"Hun");
string normal_str="Els sor.\nmsodik sor.\nutols sor.\n";
string raw_str=R"(Els sor.\nmsodik sor.\nutols sor.\n)";
cout << normal_str << endl;
cout << raw_str << endl;
}

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse

A program futsnak eredmnye:

Els sor.
msodik sor.
utols sor.
Els sor.\nmsodik sor.\nutols sor.\n

A nyers szveg kijellsre egy legfeljebb 16-karakteres tagol karaktersorozat is megadhat:


string raw_str=R"tagol(Els sor.\nmsodik sor.\nutols sor.\n)tagol";

1.7 Felhasznl ltal definilt literlok


Az j C++ nyelvben lehetsg van sajt literlok ksztsre. Az j literlt az uttagja alapjn lehet
azonostani, definilsa pedig az "" opertor tlterhelsvel trtnik:
tpus operator"" uttag(unsigned long long n) {
tpus operator"" uttag(long double d) { }
tpus operator"" uttag(const char* cstr) { }

Az egsz s lebegpontos konstans rtkek feldolgozst szmknt, illetve karaktersorozatknt egyarnt elvgezhetjk:
inline double operator"" _fok (long double fok) {
return fok*3.14159265/180;
}
double szog = 90.0_fok; // szog = 1.570796325
unsigned operator "" B(const char* bs) {
unsigned b=0;
for (int i=0; bs[i]; i++)
b = b*2 + (bs[i]=='1');
return b;
};
int maszk = 110011B; // maszk = 51

Karakter s sztring literlok esetn az albbi formk hasznlhatk, ahol a chtpus a klnbz kartertpusokat jelli (char, wchat_t, char16_t, char32_t).
tpus operator"" uttag(char c) { }
tpus operator"" uttag(const chtpus* str, size_t strhossz) {

1.8 Fordts idej konstans kifejezsek (constexpr)


A C++11 lehetv teszi, hogy olyan konstansokat, fggvnyeket s osztlyokat hozzunk ltre, amelyek felhasznlhatk ms programelemek definilsa sorn. Ennek egyetlen felttele, hogy a fordt
ltal meghatrozhat konstans rtkeket szolgltassanak. Az ilyen konstansokat, fggvnyeket s
vltozkat a constexpr kulcsszval kell definilnunk.
template<class T, int N>
constexpr int TombMeret(const T (&a)[N]) { // const is j
return N;
}
struct RGB {
unsigned char r, g, b;
constexpr RGB(unsigned char x, unsigned char y, unsigned char z):
r(x), g(y), b(z) {}
};
constexpr RGB operator+(const RGB& x, const RGB& y) { // const is j
return RGB(x.r + y.r, x.g + y.g, x.b + y.b);
}

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


int main() {
constexpr double pi=3.14159265; // const
int a[int(pi+1)] = { 12, 23, 34, 45};
int b[TombMeret(a)];
constexpr RGB piros{255, 0, 0}; // const
constexpr RGB zold{0, 255, 0}; // const
constexpr RGB kek{0, 0, 255};
// const
RGB sarga = piros+zold;
RGB cian = kek+zold;
}

is j

is j
is j
is j

A pldban piros sznnel jelltk a fordt ltal ismert konstans kifejezseket.


1.8.1 A static_assert kulcssz
A fenti megoldsok hasznlata sorn szksg lehet bizonyos ellenrzsek elhelyezsre a fordt ltal
feldolgozott kdban. A fordtsidej ellenrzsekre vezettk be a static_assert kulcsszt (szemben az
assert makrval, amely futs idej vizsglatokra szolgl):
static_assert(konstans kifejezs, sztring);

A fordt kirtkeli a konstans kifejezst, s megjelenti a sztring zenetet, ha a kirtkels eredmnye hamis. A fenti pldban ellenrizhetjk, hogy a pi konstans rtke 3 s 4 kz esik-e:
const double pi=1.14159265;
static_assert(pi>=3 && pi<=4, "Nem j az rtk");

A kvetkez fordtsi hibazenetet kapjuk: error: static assertion failed: Nem j az rtk.
1.9 Kivtelek tovbbtsnak tiltsa (noexcept)
A C++11 szabvny szerint a fggvnyekben keletkez kivtelek tovbbtsrl (a hv fel) j mdon
is dnthetnk. A fggvnyfejben a noexcept (vagy noexcept(true)) elrst megadva, a kivtelek nem
tovbbtdnak a fggvnybl, hatsukra a program futsa megszakad. Az elrst elhagyva, illetve a
noexcept(false) formban hasznlva, a kivtelek tovbbtdnak.
A noexcept kulcssz utn zrjelben egy fordts idej kifejezs llhat, amely 0 vagy nem 0 rtke
vezrli az elrs mkdst. Ebben a kifejezsben hasznlhatjuk a noexcept() opertort, amely true
rtkkel tr vissza, ha az argumentuma nem tovbbt kivteleket.
// Engedlyezi a kivtelek tovbbtst amennyiben a vector::operator[]
// is engedlyezi
void Ellenoriz(const vector<int>& v) noexcept(noexcept(v[0])) {
if (v[0] > 0) cout << "OK\n";
}
// Engedlyezi a kivtelek tovbbtst amennyiben a vector::push_back(T)
// is engedlyezi
void HozzaAd(vector<int>& v, const int elem)
noexcept(noexcept(v.push_back(elem))) {
v.push_back(elem);
}
// Nem tovbbtdik kivtel
int Meret(const vector<int>& v) noexcept {
return v.size();
}

10

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


int main() {
vector<int> v{1,2,3};
try {
Ellenoriz(v);
HozzaAd(v,4);
cout << Meret(v) << endl;
}
catch(...) {
cout << "Kivetel trtnt" << endl;
}
}

1.10 Vltozk memriahatrra igaztsa


A hagyomnyos C++ nyelvben a #pragma pack(n) elrs segtsgvel gondoskodhattunk a vltozk
memriahatrra val igaztsrl. A C++11 az alignas kulcssz bevezetsvel egyszerbb teszi ezt a
feladatot. Az albbi 10-elem tmb minden eleme 8-bjtos hatron helyezkedik el:
alignas(double) int tomb[10];

Az Adatok struktra minden pldnya 16-bjtos hatron kezddik:


struct alignas(16) Adatok {
float d[4];
};

A vltozk s a tpusok esetn alkalmazott kiigaztsrl az alignof kulcssz segtsgvel szerezhetnk


informcit:
cout << alignof(Adatok) << endl;
cout << alignof(tomb) << endl;
cout<< alignof(double) << endl;

A tpusokkal a <type_traits> fejllomny alignment_of<> osztlysablonjt is alkalmazhatjuk:


cout << alignment_of<Adatok>::value << endl;
cout << alignment_of<int>::value << endl;
cout << alignment_of<double>::value << endl

11

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse

2 j, szokatlan nyelvi megoldsok


Ebben a csoportban egy sor olyan dolgot gyjtttnk csokorba, amelyek eddig idegenek voltak a C++
nyelvtl, br ms programozsi nyelvekben tallhatunk pldkat:
automatikus tpus-meghatrozs,
jobbrtk hivatkozsok (&&),
adatok thelyezse (forward s a move),
okos (smart) mutatk,
egysges inicializls,
tartomnyalap for ciklus, a begin s az end hvsok,
- lambda kifejezsek (fggvnyek),
programkd prhuzamos futtatsa,
o aszinkron kdvgrehajts,
o szlak futtatsa,
o szlak szinkronizlsa kizrssal,
o szlak szinkronizlsa atomi vltozkkal.
2.1 Automatikus tpus-meghatrozs
A C++11 jradefinilta az auto kulcssz jelentst. Segtsgvel kzlhetjk a fordtval, hogy rbzzuk a kezdrtkkel elltott vltoz tpusnak meghatrozst. A fordt a jobb oldal tpust rendeli a
vltozhoz:
auto darab = 7;
auto pi = atan(1)*4.0;
auto p = new int[123];

// darab - int
// pi - double
// p - int *

Az auto kulcsszval hagyomnyos fggvnyeket nem definilhatunk, azonban az j visszatrsi szintaxissal mr alkalmazhatjuk:
auto Osszead(int a, double b) -> int {
return a+b;
}

Az elz megoldssal kzeli rokonsgban ll a decltype hasznlata. A decltype segtsgvel egy mr


ismert tpus vltoz (kifejezs) tpust hasznljuk a deklarlshoz:
int x = 7;
decltype(x) y;
// int y;
decltype(x) z = y; // ugyanaz, mint az auto z = y;

Az auto s a decltype egyttes hasznlatval az Osszead() fggvnynk is rtelmet nyer,


auto Osszead(int a, double b) -> decltype(a+b) {
return a+b;
}

br az igazi elnye a bemutatott megoldsoknak a sablonok hasznlata sorn jelentkezik:


template <typename T1, typename T2>
auto Osszead(T1 a, T2 b) -> decltype(a+b) {
return a+b;
}

Megjegyezzk, hogy minkt deklarci eltt szerepelhetnek a const s a volatile tpusminstk.


Nzznk egy olyan pldt, amikor igazn segti a programoz munkjt az automatikus tpusmeghatrozs:

12

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


// C++ 98 megolds
int t[4] = {12, 23, 34, 45};
vector <int> v(t, t+4);
for (vector <int>::iterator vp = v.begin(); vp!=v.end(); vp++)
cout << *vp << endl;
}
// C++11 megolds az auto alkalmazsval
int t[4] = { 12, 23, 34, 45};
vector <int> v(t, t+4);
for (auto vp = v.begin(); vp!=v.end(); vp++)
cout << *vp << endl;

2.2 Jobbrtk hivatkozsok (&&)


A C++ 98-ban a nem konstans referencikat balrtkekhez (lvalue) kthettk, a konstansokat pedig
bal-, s jobbrtkekhez egyarnt. Viszont nem volt semmi, amit hozz lehetett volna kapcsolni egy
nem konstans jobbrtkhez:
int a = 7;
int& ar = a;
const long& br = a;
const int& cr = 12;

Ezen a helyzeten vltoztatott a C++11, ahol a hivatkozsok ltalnostsaknt tekinthetnk a && opertorra:
int&&
int&&
int&&
const

xr = 23;
yr = f();
zr = a;
int&& wr = 123;

// int f() { return 123;}


// hiba, a lvalue!

// de!
auto&& dr = a;

// balrtk hivatkozs a-hoz

A jobbrtk hivatkozsok bevezetsnek igazi rtelmt a fggvnyek paramterezsben s a kvetkez rszben bemutatsra kerl thelyezs (move) szemantikban talljuk meg.
Pldaknt tekintsk az albbi kt tlterhelt fggvnyvltozatot:
const int& f(const int& a) {
return a;
}
int&& f(int&& a) {
return a+0;
}

Definiljunk vltozkat s hvjuk meg az f() fggvnyt!


int x = 123, e;
e = f(x);
// f(const int & a)
e = f(1234);

// f(int&& a)

int& y = x;
e = f(y);

// f(const int & a)

int&& z = 7;
e = f(z);

// f(const int & a)

e= f(x+y*z);

// f(int&& a)

13

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


Lthatjuk, hogy balrtk argumentum esetn az els fggvny, mg jobbrtk argumentummal a
msodik aktivldott.
2.3 Adatok thelyezse (forward s a move)
A C++ programokban ltalban nagymennyisg ideiglenes vltoz keletkezik/trldik, amelyek
tbbsgt a fordt kezeli. A C++11 megoldsokat knl az ideiglenes vltozk szmnak cskkentsre, ezzel nvelve a fut program hatkonysgt. Az adatthelyezs mkdst egyszer pldkon
szemlltetjk, azonban a sablonok ksztsnl nyjtanak igazn hathats segtsget.
A forward() fggvnysablon egy fggvny paramtereinek tovbbtst segti, ms belle hvott
fggvnyeknek:
void f(int& a) { a *= 10; }
int g(int b) { return b + 7; }
int h(int x) {
f(forward<int&>(x));
return g(forward<int>(x));
}
int main() {
int a = 12;
int b = h(a); // 127
}

A move() fggvny sokkal szlesebb krben hasznlhatjuk, elssorban nagyobb mret objektumok
esetn.
int a[5] = {2, 3, 1, 7, 9};
vector<int> v1(a, a+5);
vector<int> v2 = v1;
vector<int> v3(a, a+5);
vector<int> v4 = move(v3);

// msols
// thelyezs

A mveletek eredmnyeknt a v3 elveszti az adatait, hisz azok thelyezdtek a v4-hez. A defincis


sor utn a v1, v2 s v4 vektorok tartalmazzk az a tmb elemeit, mg a v3 egy elemek nlkli vektor
lett.
Amennyiben definiljuk az albbi Csere() fggvnysablont, a vektorok felcserlse is gyorsan elvgezhet:
template <typename T> void Csere(T& x, T& y) {
T z(move(x));
// a move konstruktor hvsa
x = move(y);
// a move opertor hvsa
y = move(z);
// a move opertor hvsa
}

Amennyiben a T tpus nem rendelkezik thelyez konstruktorral s opertorral, a minden tpushoz


rtelmezett msol konstruktort s opertort hvja a fordt.
Osztlyok esetn, az eddig ismert konstruktorok s a msol opertor kibvlt az thelyez konstruktorral s opertorral. Egy sajt kszts dinamikus tmb osztly rszletn mutatjuk be az elmondottakat:

14

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse

class DTomb { // rszlet


public:
// default s paramteres konstruktor
DTomb (int n = 12) : p( new int[n]), db(n)

{}

// copy konstruktor
DTomb (const DTomb& b) : p(new int[b.db]), db(b.db) {
for (int i = 0; i < db; ++i) p[i]=b.p[i];
}
DTomb (DTomb&& b) : p(b.p), db(b.db) { // move konstruktor
b.db = 0; b.p = nullptr;
}
DTomb& operator=(const DTomb& b) { // copy opertor
delete[] p;
db = b.db;
p = new int [db];
for (int i = 0; i < db; ++i) p[i]=b.p[i];
return *this;
}
DTomb& operator=(DTomb&& b) { // move opertor
delete[] p;
p = b.p; db = b.db;
b.db = 0; b.p = nullptr;
return *this;
}
~DTomb() { delete[] p; }
private:
int *p, db;
};
int main() {
DTomb a, b, c;
DTomb d = a, e(b);
DTomb f=move(a), g(move(b));
c = e;
c = move(e);
}

//
//
//
//

msol konstruktor
thelyez konstruktor
msol opertor
thelyez opertor

A move() fggvny valjban egy jobbrtk referencit llt el az argumentumhoz.


2.4 Okos (smart) mutatk
C++11 hrom j mutattpust (osztlysablont) is bevezetett, amelyek a hivatkozsok szmllsra s
az elrt memriaterlet automatikus felszabadtsra is kpesek (<memory> fejllomny).
unique_ptr: (egyedi mutat) akkor hasznljuk, amikor a lefoglalt memrit nem osztjuk meg (azaz az
osztly nem rendelkezik copy konstruktorral), azonban tvihet ms unique_ptr-hez (ltezik move
konstruktor).
shared_ptr: (megosztott mutat) akkor alkalmazzuk, amikor a lefoglalt memrit meg kvnjuk osztani (pl. msolssal).
weak_ptr: (gyengn megosztott mutat) shared_ptr ltal kezelt objektumra hivatkoz referencit
tartalmaz, azonban nincs hatssal a hivatkozs-szmllsra.
Az j mutatk bevezetsvel az auto_ptr elavult lett, gy hasznlata nem javasolt. Az egyedi mutatk
alkalmazst az albbi pldaprogram szemllteti:

15

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


#include <iostream>
#include <memory>
using namespace std;
struct Pelda {
int a;
Pelda()
{ cout << "Pelda::Pelda()\n"; }
~Pelda()
{ cout << "Pelda::~Pelda()\n"; }
void TagFv() { cout << "Pelda::TagFv()\n"; }
};
void KulsoFv(const Pelda& x) {
std::cout << "KulsoFv(const Pelda&)\n";
}
int main() {
unique_ptr<Pelda> p1(new Pelda);
if (p1) {
p1->a = 123;
p1->TagFv();
}

// p1 a Pelda tulajdonosa

{
unique_ptr<Pelda> p2(move(p1)); // p2 lett a Pelda tulajdonosa
KulsoFv(*p2);
p1 = move(p2); // jra p1 a Pelda tulajdonosa
cout << "p2 trlse ...\n";
}
if (p1) {
p1->TagFv();
cout << p1.get()->a << endl;
}
// a Pelda objektum megszntetse
}

A program kimenete jl mutatja az unique_ptr sablonok mkdst:


Pelda::Pelda()
Pelda::TagFv()
KulsoFv(const Pelda&)
p2 trlse ...
Pelda::TagFv()
123
Pelda::~Pelda()

A megosztott memriaterleteket is kezelhetnk a programjainkban:


int main() {
// megosztott mutathoz terletfoglals
auto p = make_shared<int>(123);
weak_ptr<int> wp = p;
{
// megosztott mutat ksztse a hivatkozott objektumhoz
auto sp = wp.lock();
cout << *sp << endl; // 123
}
// a hivatkozott objektum tulajdonjognak trlse, ha ez az utols
// shared hivatkozs volt, az objektum is trldik
p.reset();
// a hivatkozott objektum ltezsnek vizsglata
if(wp.expired())
cout << "mr trldtt" << endl;
}

16

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


2.5 Egysges inicializls
A C++98 nyelvben csak korltozottan tudtunk kezdrtket adni a tbb rtk trolsra alkalmas
vltozknak. A C++11 egysgestette a kapcsos zrjelek kztt megadott, vesszvel tagolt rtklistval trtn inicializlst. Ezzel a megoldssal lnyegesen egyszerbb vlik az STL trolk hasznlata:
#include <vector>
#include <iostream>
#include <map>
#include <set>
#include <string>
using namespace std;
long Osszeg(const vector<int>& v) {
long s = 0;
for (int e : v) // lsd 2.6 fejezet
s+=e;
return s;
};
int main() {
int tomb1[] {1,2,3,4,5};
int tomb2[] = {1,2,3,4,5};
vector<int> v1 {1,2,3,4,5};
vector<int> v2 = {1,2,3,4,5};
set<int> s1 {1,2,3,4,5};
set<int> s2 = {1,2,3,4,5};
map<int,string> m1 { {0,"nulla"}, {1,"egy"}, {2,"kett"} };
map<int,string> m2 = { {0,"nulla"}, {1,"egy"}, {2,"kett"} };
cout << Osszeg(v1) << endl;
cout << Osszeg({10,20,30,40}) << endl;
}

A kezdrtk-ads fenti mdja termszetesen ms, akr egyrtk vltozkkal is sikeresen alkalmazhat. Kln felhvjuk a figyelmet a dinamikus helyfoglals tmb inicializlsra:
int main() {
double b {};
// a tpus alaprtkvel inicializl: 0.0
char ct[7] {};
// ct minden eleme '\0' lesz
float *fp {};
// a nullptr rtket veszi fel
int a {123};
string s {"C++11"};
long *p = new long[3] {12,23,34};
delete []p;
struct {
int kor;
string nev;
} diak {9, "Ivn"};
}

Sajt kszts osztlyainkat egy initializer_list<> tpus paramtert fogad konstruktorral felkszthetjk az inicializl lista feldolgozsra.

17

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse

2.6 Tartomnyalap for ciklus, a begin s az end hvsok


A C++11 bevezette a ms nyelvekbl ismert foreach vezrlsi szerkezetet. (Nem keverend ssze a
szabvnyos knyvtr for_each() fggvnyvel, amely egy fggvnyobjektumot hajt vgre a megadott
intervallumon!) A ciklus formja:
for ( elem_deklarci : tartomny_kifejezs) utasts;

ahol a tartomny_kifejezs helyn olyan kifejezs llhat, melyre a szintn jonnan bevezetett begin()
s end() fggvnyek egyrtelmen azonostjk (mutatkkal/itertorokkal) a tartomny elejt s vgt.
A ciklus futsa sorn egy mutat/itertor vgigmegy a fentiekben kijellt tartomnyon, s minden
lpsben az elem_deklarciban megadott vltozn keresztl rhetjk el a meghivatkozott elemet.
Pldaknt vegyk a hagyomnyos (statikus) tmbket:
int a[] = {2, 7, 10, 11, 12, 23, 29, 30};

Az e vltoz sorban felveszi az a tmb minden elemnek rtkt:


for (int e : a) cout << e << " " ;

illetve hivatkozst (ekkor e tmb elemei mdosthatk):


for (int& e : a) e++;

Hasonl megoldsokhoz jutunk, amennyiben az elemtpus megllaptst a fordtra bzzuk:


for (auto e : a) cout << e << " " ;
for (auto& e : a) e++;

Szksg esetn a const s volatile tpusminstk is alkalmazhatk:


for (const auto e : a) cout << e << " " ;

A tartomny_kifejezsben elssorban a mr ismert s az j STL trolkat hasznljuk, de alkalmazhatunk tmbket (array, valarray) s inicializl listkat is
vector <double> v = {1.2, 2.3, 3.5};
for (auto e : v) cout << e << " ";
array<double,3> ar = {1.2, 2.3, 3.5};
for (auto e : ar) cout << e << " ";
valarray<double> var = {1.2, 2.3, 3.5};
for (auto e : var) cout << e << " ";
for (auto e : { 12, 23, 34, 45} ) cout << e << " ";

Mint emltettk, a for ciklussal bejrt tartomny hatrait a begin s az end hvsokkal krdezi le a
fordt, amelyek osztlyok esetn a begin() s az end() tagfggvnyek hvst jelenti. Minkt fggvny ltalnostott mutatkkal (itertorokkal) tr vissza, melyek a trolt adatok elejre, illetve a vgt kvet pozcira hivatkoznak:

begin

18

end

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


Ezek ismeretben magunk is kszthetnk trol osztlyokat, amelyek pldul dinamikus helyfoglals tmbk esetn lehetv teszik a tartomnyalap for ciklus alkalmazst. A pldban a Fibo osztly
konstruktora adott n mret dinamikus tmbben trolja a Fibonacci szmsor els n elemt.
#include <iostream>
using namespace std;
class Fibo {
int *fb = nullptr;
int db = 0;
public:
Fibo(int n = 7) {
db = n<2 ? 2 : n;
fb = new int[db] {0,1};
for (int i=2; i<db; i++)
fb[i] = fb[i-1] + fb[i-2];
}
~Fibo() { delete[] fb;}
int* begin() {return fb;}
// mutat a tmb elejre
int* end() {return fb+db;}
// mutat a tmb utni pozcira
};
int main() {
Fibo fibo(12);
for (int a: fibo)
cout << a << ' ';
for (int *p=begin(fibo); p!=end(fibo); p++)
cout << *p << ' ' ;
}

A begin s az end sablonokat az STL kontnereivel is sikeresen alkalmazhatjuk, pldul az rtktmbbel (valarray):
#include <iostream>
#include <algorithm>
#include <valarray>
using namespace std;
int main() {
valarray<double> va {25, 9, 36, 4};
sort(begin(va), end(va));
for (auto e : va)
cout << e << ' '; cout << endl;
valarray<double> vb = sqrt(va);
for (auto e : vb)
cout << e << ' '; cout << endl;
cout << va.sum() << endl;
cout << vb.max() << endl;
va = va + vb;
for (auto e : va)
cout << e << ' '; cout << endl;
fill(begin(va), end(va), 0);
for (auto e : va)
cout << e << ' '; cout << endl;
}

// 4 9 25 36

// 2 3 5 6
// 74
// 6

// 6 12 30 42

// 0 0 0 0

19

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse

2.7 - lambda kifejezsek (fggvnyek)


A lambda fggvnyek lehetv teszik, hogy egy vagy tbbsoros nvtelen fggvnyeket definiljunk a
forrskdban, ott ahol ppen szksg van rjuk. A lambda kifejezsek szerkezete nem kttt, a fordt felttelezsekkel l a hinyz rszekkel kapcsolatban. Az albbi pldban a piros sznnel kiemelt
rsz maga a lambda fggvny
int a = [] {return 12*23;} ();

A bevezet szgletes zrjelpr jelzi, hogy lamda (kifejezs) kvetkezik. Ez utn ll a fggvny trzse,
amely return utastsbl a fordt meghatrozza fggvny rtkt s tpust. Az utastst zr kerek
zrjelpr a fggvnyhvst jelenti.
Amennyiben paramterezni kvnjuk a lambdt, a fenti kt rsz kz egy hagyomnyos paramterlista is bekeldik:
int b = [] (int x, int y) { return x*y;} (12,23);

Szksg esetn a fggvny tpust is megadhatjuk a C++11-ben bevezetett formban:


double c = [] (int x, int y) -> double { return x*y;} (12,23);

Amennyiben egy lambda fggvnyt tbbszr szeretnnk hvni, hozzrendelhetjk egy fggvnymutathoz. Az albbi pldban egy tabellz fggvny argumentumaknt hasznlunk lambdkat:
#include <iostream>
#include <cmath>
using namespace std;
void Tabellaz(double a, double b, double dx, double(*pfv)(double))
{
for (double x = a; x <= b; x += dx)
cout << x << "\t" << pfv(x) << endl;
}
double (*fvptr1)(double) = [](double x)-> double {
return x*sqrt(x);
};
auto fvptr2 = [](double x)-> double {return log(x)*sqrt(x);};
int main() {
Tabellaz(1, 2, 0.2, [](double x) {return x*x;});
Tabellaz(2, 3, 0.1, fvptr1);
Tabellaz(3, 4, 0.2, fvptr2);
}

A lambda fggvnyek legfontosabb alkalmazsi terlete az STL algoritmusok hvsa. Az albbi utastsok a vector s az algorithm fejllomnyok beptse utn mkdkpesek:
vector <int> adatok = { 1, 1, 2, 3, 5, 8, 13, 21 };
int db= count_if(begin(adatok), end(adatok), [](int e){return e%2;} );
cout << "Pratlan elemek szma: " << db << endl;
for_each(begin(adatok), end(adatok), [](int& e) { e = 2*e;} );
sort(begin(adatok), end(adatok), [](int e1, int e2) { return e1>e2;} );
for_each(begin(adatok), end(adatok), [](int e) { cout << e << " ";} );

Elszr megszmlljuk az adatok vektor pratlan elemeit, majd minden elemet a dupljra nvelnk,
cskken sorrendben rendezzk a vektort, vgl pedig megjelentjk az elemeket.

20

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse

A fenti pldinkban a lambda fggvnyek csak a paramtereken keresztl tartottk a kapcsolatot a


krnyezetkben (hatkrkben) elrhet vltozkkal. Ellenttben a hagyomnyos fggvnyekkel, a
lambda kifejezsekben elrhetjk a loklis hatkr vltozit.
A fjlszint s loklis, statikus lettartam nevek elrse minden tovbbi nlkl mkdik:
double a = 3.14159265;
int main() {
static int b = 11;
double x = [] () { return a+b;} ();
}

A loklis, nem statikus fggvnyvltozk, illetve az osztly adattagjai esetn intzkedhetnk az elrs
mdjrl. Amennyiben a fenti pldban az a s b loklis vltozk, a velk azonos hatkrben megadott lambda a kvetkezkppen mdosul:
int main() {
double a = 3.14159265;
int b = 11;
double x = [a,b] () { return a+b;} ();
cout << x << endl;
}

A lambdt s az elrt vltozkat egytt szoks bezrsnak (closure) nevezni, mg a felhasznlt vltozkra, mint elkapott (captured) vltozkra hivatkozunk. A vltozkat rtkk szerint s hivatkozsukkal egyarnt elkaphatjuk, az albbi pldkban bemutatott mdon:
[]
[=]
[&]
[a, b]
[a, &b]
[=, &b]
[&, a]
[this]

Egyetlen helyi vltozt sem kvnunk elkapni.


Az sszes helyi vltozt rtk szerint kapjuk el.
Az sszes helyi vltozt referencijval kapjuk el.
Csak az a s b vltozkat kapjuk el, rtk szerint.
Az a vltoz rtk szerint, a b vltozt azonban a referencijval kapjuk el.
Az sszes helyi vltozt rtk szerint kapjuk el, kivve a b vltozt, amelyet a
hivatkozsa rvn.
Az sszes helyi vltozt a referencijukkal kapjuk el, kivve az a vltozt,
amelyet rtk szerint.
Az osztlyon bell definilt lambda kifejezsekben hasznlhatjuk a this mutatt, vagyis elrhetjk az osztly tagjait.

A fordt alaphelyzetben nem engedi az rtk szerint elkapott vltozk rtknek mdostst. Ha
azonban a fggvny trzse eltt megadjuk a mutable kulcsszt, a mdosts elvgezhet, azonban
rvnyessge a lambdra korltozdik.
int main() {
int x = 7, y = 12;
int z = [=] () mutable { ++x, ++y; return x*y;} ();
cout << x << y << z << endl; // 7 12 104
}

Referencival trtn elkaps esetn egszen ms a helyzet:


int main() {
int x = 7, y = 12;
int z = [&] () { ++x, ++y; return x*y;} ();
cout << x << y << z << endl; // 8 13 104
}

21

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


A lambda fggvnyek esetn is szablyozhatjuk a kivtelek tovbbtst. Alaphelyzetben minden
kivtel tovbbtdik a hv fggvnynek:
auto lambda1 = []() { };

De igny szerint korltozhatjuk a tovbbtott kivteleket:


auto lambda3 = []() throw(int, char*) { };

vagy akr le is tilthatjuk azok tovbbtst:


auto lambda2 = []() throw() { };

A C++11 nyelvben bevezetett function<> sablon (functional fejllomny) nagyban segti a lambda
fggvnyek hasznlatt. Segtsgvel a tabellz programunk jval olvashatbb formt lt:
#include <iostream>
#include <cmath>
#include <functional>
using namespace std;
void Tabellaz(double a, double b, double dx,
function<double(double)> fv) {
for (double x = a; x <= b; x += dx)
cout << x << "\t" << fv(x) << endl;
}
function<double(double)> fv1 = [](double x)-> double {
return x*sqrt(x);
};
function<double(double)> fv2 = [](double x)-> double
{return log(x)*sqrt(x);};
int main() {
Tabellaz(1, 2, 0.2, [](double x) {return x*x;});
Tabellaz(2, 3, 0.1, fv1);
Tabellaz(3, 4, 0.2, fv2);
}

A function<> sablon felhasznlsval rekurzv lambdt is kszthetnk:


int main() {
function<int(int)> fakt = [&fakt] (int n) {
if (n < 2) return 1; else return n*fakt(n-1);};
cout << fakt(5) << endl; // 120
}

2.8 Programkd prhuzamos futtatsa


A prhuzamossg (concurrency) s a tbbszlsg (multithreading) azt jelenti, hogy programunk bizonyos rszei (fggvnyei) egyszerre hajtdnak vgre. Tbbmagos processzorok vilgban ezzel jelensen nvelhetjk programunk hatkonysgt.
A C++98 futtat krnyezete egyetlen programszl futtatsra volt felksztve. Ennek kvetkeztben a
tbbszlsg bevezetshez a C++11 futtat krnyezett alapveten t kellet dolgozni. A nyelv defincija csupn a thread_local trolsi osztly bevezetsvel tmogatja a tbbszl programok ksztst, az igazi tudst C++ sablontr elemeivel rjk el. Egy thread_local vltoz a r hivatkoz programszl indtsakor jn ltre, s a szl befejezsekor megsznik, gy minden szl sajt msolattal rendelkezik belle.

22

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


Mint emltettk, a C++11 gazdag knyvtrat biztost a tbbszl programok ksztshez az
<atomic>, a <thread>, a <mutex>, a <future> s a <condition_variable> fejllomnyok definciival.
A prhuzamosan indtott fggvnyek futhatnak egymstl fggetlenl, aszinkron mdon (async),
illetve egymshoz szinkronizlva (thread). Az aszinkron fggvnyek, amelyek visszatrsi rtke elrhet, jl hasznlhatk bizonyos szmtsok elvgzshez, illetve perifrik kezelsre. Brmelyik
esetet is vlasztjuk, a futtatni kvnt fggvnyt (funkcionlt) tbbflekppen is megadhatjuk:
fggvnymutatval (a fggvny nevvel),
tagfggvny mutatval,
lambda kifejezsknt,
fggvny objektummal (amely definilja az operator() tagfggvnyt).
2.8.1 Aszinkron kdvgrehajts
Fggvnyek aszinkron futtatst a <future> fejllomnyban deklarlt async() fggvnysablon segtsgvel kezdemnyezhetjk.
A fggvnysablonnak els argumentumknt a futtatni kvnt kdot tartalmaz funkcionlt adjuk t, a
tovbbi argumentumok pedig a hvott fggvnyhez tovbbtdnak. (Hivatkozssal trtn paramtertadshoz az argumentumokat a ref() fggvnysablonnal kel beburkolni.)
future<void> fv = async(Kiir, "async: ");

Az async() sablon msik vltozatban az els argumentum a futtats mdjt hatrozza meg:
auto fv = async(launch::deferred, Kiir, "async: ");

ennek lehetsges rtkei:


launch::async a kd egy j programszlban fut (ez az alaprtelmezs),
launch::deferred a kd az aktulis szlban hajtdik vgre aszinkron mdon (lusta vgrehats).
Az async() hvs egy future<fggvnytpus> objektummal tr vissza, mely objektumon keresztl elrhetjk az aszinkron fggvny visszatrsi rtkt (a get() tagfggvny hvsval), valamint a futs
sorn keletkezett kivteleket.
#include <future>
#include <iostream>
#include <string>
using namespace std;
void Kiir(string const& str) {
for (int i=0; i<100; i++)
cout << str << i << endl;
}
int main() {
future<void> fv = async(Kiir, "async: ");
for (int i=0; i<100; i++)
cout << "main: " << i << endl;
fv.wait();
}

main:
async:
main:
async:
async:
main:
async:
main:
async:
main:
async:
async:
main:
async:
async:
main:

0
0
1
1
2
2
3
3
4
4
5
6
5
7
8
6

A fenti pldban, a fszlban (main()) s az aszinkron szlban (Kiir()) egy-egy for ciklus fut, melyek
futsi eredmnynek els pr sora a jobb oldali oszlopban lthat. Az aszinkron kd befejezst a
future< > osztlysablon wait() tagfggvnyvel vrhatjuk meg.

23

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


Tovbbi lehetsgeket biztostanak a wait_for() s a wait_until() tagfggvnyek, amelyek a
future_status felsorols elemeivel jelzik, hogy az eredmny rendelkezsre ll-e adott id mlva, illetve adott idpont elrst kveten, vagy sem.
#include <future>
#include <iostream>
#include <string>
#include <chrono>
using namespace std;
int main() {
cout << "vrakozik..." << endl;
int allapot;
future<int> ft = async(launch::async, [] () {
this_thread::sleep_for(chrono::seconds(2));
return 123;
});
do {
allapot = ft.wait_for(chrono::milliseconds(500));
if (allapot == future_status::deferred)
cout << "mg nem indult el" << endl;
else if (allapot == future_status::timeout)
cout << "timeout" << endl;
else if (allapot == future_status::ready)
cout << "ksz" << endl;
} while (allapot != future_status::ready);
cout << "az eredmny " << ft.get() << '\n';
}

A program futsnak eredmnye:

vrakozik...
timeout
timeout
timeout
ksz
az eredmny 123

A <future> fejllomny tovbbi osztlysablonjai (promise<>, packaged_task<>, shared_future<> stb.)


bvtett lehetsgekkel tmogatjk az aszinkron kdrszletekbl felpl programok szleskr alkalmazst.
2.8.2 Szlak futtatsa
Futtathat szlat a thread osztly objektumaknt hozzuk
ltre, amely a ltrehozssal el is indul. A szlobjektum
get_id() tagfggvnynek hvsval megtudhatjuk a szl
azonostjt, a join() hvsval megvrhatjuk a szl lefutst,
mg a detach() hvssal levlaszthatjuk a fut szlat a szlobjektumrl.
Felhvjuk a figyelmet arra, hogy nincs md a szlban fut
fggvny visszatrsi rtknek elrsre! (Szksg esetn a
fggvnybl referencia paramterek segtsgvel nyerhetnk ki adatot.)

24

main() programszl

programszl
ltrehozsa

programszl.join()

main() programszl

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


A fenti aszinkron pldaprogram programszlat hasznl vltozata:
#include <thread>
#include <iostream>
#include <string>
using namespace std;
void Kiir(string const& str) {
for (int i=0; i<100; i++)
cout << str << i << endl;
}
int main() {
thread td (Kiir, "thread: ");
for (int i=0; i<100; i++)
cout << "main:
" << i << endl;
td.join();
cout << "main thread ID: "
<< this_thread::get_id() << endl;
cout << "Kiir thread ID: " << td.get_id() << endl;
}

thread:
main:
main:
thread:
thread:
thread:
thread:
thread:
thread:
main:
thread:
thread:
main:
main:
main:
main:
main:
main:
main:

0
0
1
1
2
3
4
5
6
2
7
8
3
4
5
6
7
8
9

Az aktulis szlra (a szlat megvalst fggvnyen bell) a this_thread nvtr fggvnyeivel is hivatkozhatunk:
lekrdezhetjk a szl azonostjt
get_id(),
javasolhatjuk, hogy vezrls a szltl addjon t ms szlakhoz: yield(),
megadott ideig felfggeszthetjk a szl futst:
sleep_for(idtartam),
#include <chrono>
#include <thread>
using namespace std::chrono;
int main() {
std::this_thread::sleep_for(seconds(10));
}

adott idpontig is blokkolhatjuk a szl futst:

sleep_until(idpont).

#include <chrono>
#include <thread>
using namespace std::chrono;
int main() {
std::this_thread::sleep_until(system_clock::now() + seconds(10));
}

25

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse

2.8.3 Szlak szinkronizlsa kizrssal


A mutex (mutual exclusion kzs kizrs) objektum tbb szl ltal hasznlt, osztott erforrsok
vdelmre alkalmas eszkz. Segtsgvel a szlon bell kritikus szekcit hozhatunk ltre, amelyet
egyszerre csak egy szl rhet el. A fut szl mellett a tbbi, ugyanazt a fggvnyt vgrehajt szl
vrakozik.
#include <iostream>
#include <thread>
#include <mutex>
using namespace std;
void fv(char t, mutex& m) {
for (auto i = 0; i < 5; i++) {
m.lock();
cout << t << ": " << i << endl;
m.unlock();
}
}
int main() {
mutex m;
thread t1(fv, 'A', ref(m));
thread t2(fv, 'B', ref(m));
thread t3(fv, 'C', ref(m));
t1.join();
t2.join();
t3.join();
}

mutex nlkl:
A: 0
B: 0
B: 1
B: 2
B: 3
B: 4
C: 0
C: 1
C: 2
A: 1
A: 2
A: 3
A: 4
C: 3
C: 4

mutex-szel:
A: 0
B: 0
C: 0
A: 1
B: 1
C: 1
A: 2
B: 2
C: 2
A: 3
B: 3
C: 3
A: 4
B: 4
C: 4

A kizrs elvgzsre tbb, a <mutex> fejllomnyban deklarlt osztly kzl is vlaszthatunk, melyek neve utal a felhasznlsi mdjukra: mutex, recursive_mutex, timed_mutex,
recursive_timed_mutex. Mindegyik osztly biztostja szmunkra a lock(), try_lock() s az unlock()
tagfggvnyeket.
mutex m;
if (m.try_lock() == true) {
cout << " Megtrtnt a kizrs" << endl;
m.unlock();
} else
cout << "Sikertelen kizrs" << endl;

A rekurzv mutex-et akkor hasznljuk, ha egy szlban tbb kizrs is elfordul. Norml kizrs (mutex)
esetn az ilyen szlak nem tudjk befejezni a futsukat (elll deadlock llapot). Az idztett kizr
objektumokkal adott ideig try_lock_for() vagy adott idpontig try_lock_until () prblkozhatunk a
kizrssal.
Tovbbi lehetsget biztost a lock_guard<> osztlysablon hasznlata, melynek konstruktorban jn
ltre a kizrs, mg a destruktorban automatikusan meg is sznik az.
int n = 0;
mutex n_mutex;
void BiztonsagosLeptetes() {
lock_guard<mutex> kizaras(n_mutex);
++n;
}

26

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


Tovbbi megoldst ad a keznkbe az unique_lock<> , az univerzlis kizr osztlysablon, amely a fent
bemutatott megoldsokon tlmenen lehetv teszi a kizrsi stratgia (defer_lock, try_to_lock,
adopt_lock) megadst is. Az unique_lock<> sablonnal egytt hasznlhatjuk a <conditional_variable>
fejllomnyban deklarlt a conditional_variable osztlyt, amely a kizrst rtestskldsi lehetsggel vrtezi fel.
2.8.4 Szlak szinkronizlsa atomi vltozkkal
A C++11 az <atomic> fejllomnyban definilt atomic<> osztlysablonnal, s annak egszekre specializlt vltozataival tmogatja az atomi mveletek vgzst. Az atomi mveletek oszthatatlanok, vgrehajtsuk nem szakadhat meg. Ezltal az atomi vltozk s a rajtuk vgzett mveletek szl biztosak
(thread-safe), gy felhasznlhatk a szlak automatikus szinkronizlsra.
Az albbi pldban definilt Szamlalo<> osztlysablon tagfggvnyei szlbiztos mdon vgzik a szam
tagjnak lptetst, rtknek belltst s lekrdezst:
#include <iostream>
#include <atomic>
using namespace std;
template <typename T>
struct Szamlalo {
Szamlalo(T e) { Set(e); }
atomic<T> szam;
void Novel() { ++szam; }
void Csokkent() { --szam; }
T Get() { return szam.load(); }
void Set(T e) { szam.store(e); }
};
int main() {
Szamlalo<int> n(12);
for(int i=0; i<112; i++) n.Novel();
n.Csokkent();
cout << n.Get() << endl;
}

Az utols, tbb szlat futtat pldban a szlakkal kt nagy vektor skalris szorzatt szmoljuk, felosztva a tmb elemeit a szlak kztt:
#include <iostream>
#include <thread>
#include <vector>
#include <atomic>
using namespace std;
atomic<int> eredmeny(0);
void SkalarSzorzat(const vector<int> &v1, const vector<int> &v2,
int kezdo, int vegso) {
int reszOsszeg = 0;
for(int i = kezdo; i < vegso; ++i) {
reszOsszeg += v1[i] * v2[i];
}
eredmeny += reszOsszeg;
}
int main() {
const int elemszam =100000;
const int szalszam = 5;
vector<thread> szalak;

27

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


// v1={2,2,2,2,...,2}, v2={3,3,3,3,...,3}
// A skalrszorzat eredmnye 600000
vector<int> v1(elemszam,2), v2(elemszam,3);
// Az elemek felosztsa a szlak kztt
vector<int> hatarok;
for (int n=0; n<szalszam; n++)
hatarok.push_back(n*elemszam/szalszam);
hatarok.push_back(elemszam);
// A szlak indtsa:
for (int i = 0; i < szalszam; i++)
szalak.push_back(move( thread(SkalarSzorzat, cref(v1),
cref(v2), hatarok[i], hatarok[i+1])) );
// A szlak lefutsnak bevrsa
for (auto &t : szalak)
t.join();
cout << eredmeny << endl;
}

28

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse

3. Vltozsok az osztlyok s a sablonok krben


A C++11 nyelv sszes lehetsgt mrlegre helyezve, a mrleg nyelve ebben a csoportban bemutatott megoldsok oldalra billen. nmagukban az osztlyok ksztsnek szablyai ugyan alig vltoztak, azonban a sablonok szintjn trtn fejleszts eltt j tvlatok nyltak:
konstruktorok deleglsa, adattagok inicializlsa, sizeof adattagra,
opertorfggvnyek explicit tpus-talaktssal,
az override s a final mdostk,
a delete s a default tagfgvnyek,
korltozsok nlkli union tpus,
sablonok s a C++11,
o szintaxis,
o kls sablonok,
o sablon lnevek (template alias),
o sablonok vltoz hosszsg argumentumlistval (variadic templates),
o htravetett visszatrsi tpus (suffix return types).
3.1 Konstruktorok deleglsa, adattagok inicializlsa, sizeof adattagra
A konstruktorok deleglsa lehetv teszi, hogy ugyanazon osztlyon bell az egyik konstruktorbl
egy msikat hvjunk. A msik konstruktor hvst a konstruktorfejben, az inicializl listn kell elhelyeznnk.
#include <iostream>
using namespace std;
class Pont {
int x,y;
public:
Pont(int a, int b) :x(a), y(b) {}
Pont() : Pont(0,0) {}
Pont(Pont& p) : Pont(p.x, p.y) {}
// ...
};
int main() {
Pont a, b(12,23);
Pont c {b};
}

Ez a megolds kell odafigyelst ignyel, hisz nem ajnlott rekurzv konstruktorhvsba keverednnk.
Nem tl lnyeges jdonsg, azonban rdemes tudni rla, hogy ezentl a sizeof mvelet az osztlyok
adattagjaira is elvgezhet, az osztlyok pldnyostsa nlkl. Ugyancsak ritkn hasznlt megoldsknt a C++11 biztostja, hogy az osztlyok nem statikus s nem konstans adattagjait kezdrtkkel
lssuk el az osztlydefincin bell.
#include <iostream>
using namespace std;
class Adattar {
private:
double d=12;
public:
long b=123;
char v[7] = {'O', 'O', '\0'};
void Kiir() {
cout << sizeof(Adattar::d) << endl; // 8
}

29

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


};
int main() {
cout << sizeof(Adattar::b) << endl;
cout << sizeof(Adattar::v) << endl;
Adattar a;
cout << sizeof(a.b) << endl;
a.Kiir();
}

// 4
// 7
// 4

3.2 Opertorfggvnyek explicit tpus-talaktssal


A C++ 98 az explicit kulcsszval azt jelli, hogy egy konstruktor nem hasznlhat implicit konverzira.
Az j szabvny lehetv teszi, hogy a kulcsszt konverzis opertorokkal is alkalmazzuk, kizrva ezzel
az implicit tpus-talaktsokat.
Az albbi Komplex osztlyban pldt ltunk az explicit kulcssz minkt alkalmazsra. Az explicit talaktsok kijellsvel ksztett main() fggvny termszetesen a kevsb szigor esetben is jl mkdik. (A lap jobb oldaln az implicit talaktsokkal ksztett main() fggvny lthat.)
class Komplex {
public:
Komplex(double a, double b) {re=a; im=b;}
// konverzis konstruktor
explicit Komplex(double a) { re=a; im=0; }
// konverzis opertor
explicit operator double() const {return sqrt(re*re+im*im);}
private:
double re, im;
};
int main() {
Komplex a(3,4);
Komplex b(123.0);
double x = static_cast<double>(a);
double y = double(b);
int c = double(Komplex(123));
}

int main() {
Komplex a(3,4);
Komplex b = 123.0;
double x = a;
double y = b;
int c = Komplex(123);
}

3.3 Az override s a final mdostk


A C++ nyelven az osztlyok tagfggvnyeinek virtulis volta nem ktelez (mint pldul a Java nyelvben). A programoz a virtual kulcssz segtsgvel jelli ki a virtualits kezdett egy rklsi lncon
bell.
Amennyiben a virtulis tagfggvnyt tartalmaz alaposztlybl j osztlyt szrmaztatunk, s ott a
virtulis fggvnnyel megegyez nev fggvny ksztnk, kt eset ll fenn:
ha az j fggvny prototpusa megegyezik a virtulis fggvnyvel, a fordt lecserli az alaposztlybeli virtulis fggvnyt az j fggvnnyel (jradefinils, overriding),
ha azonban a paramterek tpusa eltr, az jradefinils helyett a tlterhels (overloading)
mechanizmusa rvnyesl, s mindkt fggvny elrhet lesz az j osztlyban. Az alaposztly
mutatjn keresztl hivatkozva az j objektumra, az alaposztlybeli fggvny hvdik meg.
Erre ltunk pldt az albbi egyszer programban:
class B {
public:
virtual void fv(int) {cout << "B::fv()" << endl;}
};

30

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


class D : public B {
public:
void fv(long) {cout << "D::fv()" << endl;}
};
int main() {
B b;
B *p = &b;
p->fv(12);
D d;
p = &d;
p->fv(23);
}

// B::fv()

// B::fv()

Amennyiben a D osztly int tpus paramterrel definilja a D::fv() tagfggvnyt, a msodik hvskor
a D-beli fv() aktivizldik.
Az jonnan bevezetett override mdostval jelezhetjk a fordtnak, hogy virtulis fggvnyt szeretnnk jradefinilni. Ha azonban ennek felttelei nem llnak fenn (pl. eltr paramtertpusok),
fordtsi hibt kapunk.
class D : public B {
public:
void fv(long) override {cout << "D::fv()" << endl;}
};

A final mdostval pedig pp ellenkezleg, megakadlyozhatjuk az adott virtulis fggvny lecserlst a szrmaztatott osztlyokban:
class B {
public:
virtual void fv(int) final
};

{cout << "B::fv()" << endl;}

A kt mdost megfelel kontextusban egytt is hasznlhat, gy egy ksbbi szrmaztats sorn


meggtolva a lecserlt virtulis fggvny tovbbi jradefinilst:
class B {
public:
virtual void fv(int) {cout << "B::fv()" << endl;}
};
class D : public B {
public:
void fv(int) override final {cout << "D::fv()" << endl;}
};
int main() {
B b;
B *p = &b;
p->fv(12);
D d;
p = &d;
p->fv(23);
}

// B::fv()

// D::fv()

31

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


Amennyiben a final elrst az osztly neve utn adjuk meg, akkor abbl az osztlybl nem lehet j
osztlyt szrmaztatni:
class A final {};
class B : public A {}; // hiba!

3.4 A delete s a default tagfgvnyek


A C++ fordt egy sor tagfggvnyt hoz ltre automatikusan, amennyiben mi nem definiljuk azokat.
C++98-ban egyetlen szably volt, hogy a fordt ltal ksztett paramter nlkli konstruktor nem jn
ltre, amennyiben brmilyen konstruktort definilunk. C++11-ben minden automatikusan ltrejv
tagfggvnyrl magunk dnthetnk, krhetjk az elksztsket (default), illetve elutasthatjuk azt
(delete). A kulcsszavak hasznlatt s mkdst az albbi osztly szemllteti:
class C {
public:
C() = default;
C(const C&) = default;
C(C&&) = delete;
C& operator=(const C&) = default;
C& operator=(C&&) = delete;
virtual ~C() = default;
};

// C a; ok
// C b(c); ok
// C c(move(b)); nem ok
// b = a; ok
// a = move(c); nem ok

A C++ osztlyokhoz osztlyszint opertor-fggvnyeket (&, *, ->, ->*, new, delete) definil a fordt,
melyek hasznlatt meg is tilthatjuk. Az albbi pldban az S osztly nem pldnyosthat a dinamikus trterleten:
struct S {
void *operator new(size_t) = delete;
void *operator new[](size_t) = delete;
};
int main() {
S *p = new S;
// hiba
S *q = new S[3]; // hiba
S s;
S t[7];
}

Megjegyezzk, hogy sajt (virtulis) tagfggvnyeinket is ellthatjuk a delete kulcsszval. Ezzel a


szrmaztatott osztlyban megakadlyozhatjuk a trlt fggvnnyel megegyez prototpus fggvny
ksztst.
3.5 Korltozsok nlkli union tpus
A C++11 jelentsen cskkentette azokat a korltozsokat, amelyek megszabtk, hogy mit helyezhetnk el a union tpusban (pldul nem lehetett konstruktorral vagy destruktorral rendelkez tpus
tagja). Azonban tovbbra sem lehetnek az uink tagjai a virtulis fggvnyek s a referencik.
#include <iostream>
using namespace std;
struct Vektor2D {
int x, y;
Vektor2D(int x = 0, int y = 0) : x(x), y(y) {}
};

32

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


union Unio {
int a;
double b;
Vektor2D p;
Unio() {new(&p) Vektor2D(12,23);}
~Unio() {};
};
int main() {
Unio u;
cout << u.a << endl;
cout << u.b << endl;
}

// 12
// 4.88059e-313

Az unik hasznlatnak szabadd ttelt elssorban az alkalmazsfejlesztk tmogatjk, a hardver


kzeli programozk inkbb veszlyesnek tartjk, s javasoljk megmaradni a korbbi korltozsoknl.
3.6 Sablonok s a C++11
A fent bemutatott megoldsok tbbsge egyetlen irnyba, a sablonok irnyba mutat. Egyarnt egyszerbb s hatkonyabb teszik a sablonok hasznlatt s ksztst.
3.6.1 Szintaxis
C++98-ban a >> karaktersorozat minden esetben a jobbra val biteltols mvelett jelentette, gy
egymsba gyazott sablonok alkalmazsakor tagol karaktert kellett a kt zr > jel kz tenni. Az j
szabvnyban azonban az egymsba gyazott sablonok lezrsa lvez elsbbsget, gy nem szksges
szkzzel elvlasztanunk a nagyobb jeleket.
map <int, vector<double>> b;

// C++98, C++11 OK

map <int, vector<double>> a;

// C++11 OK

3.6.2 Kls sablonok


Amennyiben egy teljesen specializlt sablon elfordult egy fordtsi egysgben, akkor a C++ 98 fordtnak ktelez volt a fordtsi egysgen bell pldnyostania. Ez szerencstlen esetben igen megnvelhette a fordtsi idt.
A C++11 engedlyezi extern kulcssz hasznlatt a specializlt sablonokra, mellyel jelezhetjk a fordtnak, hogy az adott fordtsi egysgben ne pldnyostsa az adott sablont:
// Sablon.h: - a sablon-deklarci
template <typename T>
class Sablon {
public:
void fv(T a);
};
// Sablon.cpp - a sablon-defnici
#include <iostream>
#include "Sablon.h"
template <typename T>
void Sablon<T>::fv(T a) {
std::cout << a << std::endl;
}
// explicit pldnyosts
template class Sablon<int>;

33

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


// main.cpp
#include "Sablon.h"
extern template class Sablon<int>;
int main() {
Sablon<int> teszt;
teszt.fv(123);
return 0;
}

3.6.3 Sablon lnevek (template alias)


A C++98-ban a typedef kulcsszval csak konkrt tpusokhoz rendelhettnk szinonim nevet, azonban
nem volt lehetsg arra, hogy a sablonok nhny paramtert lektve, j sablonokat hozzunk ltre.
A C++11 szabvny a using kulcssz felhasznlsval megoldst knl erre a problmra.
#include <string>
#include <map>
#include <array>
using namespace std;
template <typename T1, typename T2>
using dictionary = map<T1, T2>;
template <typename T>
using strmap = map<string, T >;
template <size_t N>
using intarray = array<int, N>;
int main() {
dictionary<int, int> trans;
trans[12] = 23;
trans[7] = 29;
strmap<string> szotar;
szotar["one"] = "egy";
szotar["two"] = "kett";
intarray<5> itomb = {12,23, 34, 45, 56};
itomb[3] += 102;
}

Osztlysablonok esetn egyarnt kszthetnk lnevet az eredeti sablonhoz, vagy annak tetszleges
specializcijhoz. Fggvnysablonok esetn azonban nem rnk clt ilyen egyszeren.
template <typename T1, typename T2>
double f(T1 a, T2 b) {
return double((a+b)/2.0);
template <typename T>
double fa(T x) {
return f<int, T>(100, x);
}

Egy ltalnosabb megoldshoz tovbbi sablonokkal kapcsolatos megoldsokkal is meg kell ismerkednnk:
template <typename... Args>
auto g(Args&&... args) -> decltype(f(forward<Args>(args)...)) {
return f(forward<Args>(args)...);
}

34

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


3.6.4 Sablonok vltoz hosszsg argumentumlistval (variadic templates)
A sablonok hasznlata a C++ nyelv egyik legfontosabb jellemzje, amely a vltoz hosszsg argumentumlista kezelsvel mg hatkonyabb eszkzt ad a programozk kezbe. Segtsgkkel a szabvnyos knyvtr tbb, tetszleges szm argumentumot - tpusbiztos mdon - fogad fggvnysablonnal bvlt (thread(), bind(), function()), tovbb megjelent a tetszleges mret s szerkezet
rekordok ksztst tmogat osztlysablon (tuple).
A varins osztlysablonok ksztsnek szintaxisa megegyezik a szabvnyos sablonokval azzal a klnbsggel, hogy az utols paramter eltt hrom pont (...) szerepel. Pldul, a tuple osztlysablon
defincija:
template <typename... Tipusok>
class tuple;

A varins argumentum tpusokat, vagy skalr rtkeket tartalmazhat. A varins argumentumokat


sabloncsomagnak nevezzk (template pack), amely nulla vagy tbb aktulis paramterbl ll.
Az els pldban olyan osztlysablont hozunk ltre, amely pldnyai adott (egsz) tpus statikus
tmbt tartalmaz (tomb), melyet varins argumentumokknt megadott elemekkel fel is tltnk. A
pldban a sizeof opertorral a paramtercsomagban megtallhat paramterek szmt krdeztk
le.
template <typename T, T... elemek>
struct StatikusTomb {
T tomb[sizeof...(elemek)] = {elemek...};
};
int main() {
StatikusTomb<int, 12,23,34,45> x;
for (int e : x.tomb)
cout << e << " ";
StatikusTomb<char, 'A', 'B', 'C'> y;
for (char e : y.tomb)
cout << e << " ";
}

Az albbi varins Rekord osztlysablon tetszleges szm s tpus adat egyttest kpes kezelni, br
elgg krlmnyes mdon.
#include <string>
#include <iostream>
using namespace std;
// A sablon deklarcija
template<typename ... Tipusok>
class Rekord;
// A rekurzv feldolgozs vgt jelz, res paramterlistj sablon
template<>
class Rekord<> {};
// Legalbb egy paramtert tartalmaz specializlt sablonvltozat.
// Az N elem paramterlistt, egy elem plusz N-1 elem
// paramterlistaknt dolgozza fel, rekurzv mdon.
template<typename Elso, typename ... Maradek>

35

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


class Rekord<Elso, Maradek...> : Rekord<Maradek...> {
Elso adat;
public:
Rekord(Elso const& elso, Maradek const& ... maradek) :
Rekord<Maradek...>(maradek...), adat(elso) { }
Elso const& Fej() const {
return adat;
}
Rekord<Maradek...> const& Tobbi() const {
return *this;
}
};
// A Rekord sablon hasznlata
int main() {
Rekord<int, double, string> r(2011, 8.12, "C++11");
cout << r.Fej() << endl;
// 2011
cout << r.Tobbi().Fej() << endl;
// 8.11
cout << r.Tobbi().Tobbi().Fej() << endl;
// C++11
}

A varins fggvnysablonok tpusparamtereit az osztlyokhoz hasonl mdon hasznlhatjuk, azonban itt tetszleges szm fggvnyargumentumbl ll el a tpuslista. A feldolgozst rekurzv mdon
vgezzk, ahol a rekurzis lnc vgt egy egyparamteres, tlterhelt fggvnysablon biztostja.
#include <iostream>
using namespace std;
template <typename T>
void Kiiras(T t) {
cout << t;
}
template <typename Elso, typename... Argumentomok>
void Kiiras(Elso e, Argumentomok... argumentumok) {
cout << e << " ";
Kiiras(forward<Argumentomok>(argumentumok)...);
}
template <typename T>
T Osszeg(T t) {
return t ;
}
template <typename T, typename ...P>
T Osszeg(T t, P ...p) {
if (sizeof...(p))
t += Osszeg(p...);
return t;
}
int main() {
int a=12;
double b=12.23;
string c = "C++11";
Kiiras(a, b, c, '\n'); // 12 12.23 C++11
cout << Osszeg(12,23) << endl; // 35
}

36

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


3.6.5 Htravetett visszatrsi tpus (suffix return types)
A C++98 nyelven sokszor problmt jelentett a fggvnysablonok visszatrsi tpusnak megadsa.
Gyakran alkalmazott megolds volt, hogy egy tovbbi sablonparamtert hasznltunk erre a clra:
template <typename R, typename S, typename T>
R Atlag1(S a, T b) {
return (a+b)/2;
}

Az Atlag1() fggvny hvsai:


cout << Atlag1<int, int, int>(9, 4) << endl;
// 6
cout << Atlag1<double, double, int>(9.5, 4) << endl; // 6.75
A C++11 j fggvnymegadsi formt vezetett be, amelyben a decltype kulcssz is hasznlhat a
visszatrsi rtk meghatrozsra:

template <typename S, typename T>


auto Atlag2(S a, T b) -> decltype ((a+b)/2) {
return (a+b)/2;
}

Az Atlag2() fggvny hvsai:


cout << Atlag2(9, 4) << endl;
cout << Atlag2(9.5, 4) << endl;

// 6
// 6.75

Termszetesen ez a megolds osztlysablonok tagfggvnyei esetn is alkalmazhat.

37

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse

4. A C++11 knyvtr jdonsgai


A szabvnyos C++ knyvtr tbb oldalrl is bvlt. Egyrszt a C11 nyelvbl tvett megoldsok miatt
j, hasznos fggvnyek jelentek meg, amelyek a nevkben hordozzk a kapcsold tpust. Msrszt
pedig az STL rsz jabb elemekkel gazdagodott. Valjban a C++98 sablontr is jjszletett, hiszen a
sablonok tbbsge tmogatja az thelyezst (move) valamint az inicializl lista alkalmazst.
Ebben a fejezetben kvetjk ezt a kettssget, azonban az j sablonokat csoportostva mutatjuk be.
Felhvjuk a figyelmet arra, hogy semelyik rsz sem helyettesti a hivatalos C++11 STL hivatkozsok
gyjtemnyt. Clunk egy tfog kpet adni a C++11 szabvnyos knyvtra ltal nyjtott lehetsgekrl:
j fggvnyek s tagfggvnyek a C++ knyvtrban,
o C-sztring tartalmnak szmm alaktsa,
o a string tpus s a numerikus adatok kztti talaktsok,
o Unicode karakterek s sztringek talaktsa,
o j matematikai fggvnyek,
o a bvtett complex osztlysablon,
o fordts idej racionlis aritmetika,
vletlen szmok ellltsa,
id- s dtumkezels,
regulris kifejezsek knyvtra,
kibvtett tpuskezel knyvtr,
polimorf fggvnyobjektumok,
inicializl lista sajt osztlyokban,
vltozsok a kontnerek (trolk) knyvtrban,
o kezdrtkads a kontnereknek,
o a move szemantika s az STL kontnerek,
o a begin, end s swap fggvnysablonok hasznlata,
kibvtett algoritmus knyvtr,
rekordok j megkzeltsben (tuple),
a szabvnyos C++ nyelv deklarcis llomnyai.
4.1 j fggvnyek s tagfggvnyek a C++ knyvtrban
A szabvnyos C11 nyelvvel val minl nagyobb kompatibilits rdekben, a C fggvnyknyvtr elemeinek tbbsge is megjelent a C++11 nyelv szabvnyos knyvtrban. Emellett azonban nhny
C++ fggvny is kszlt, a szmok s a szvegek kztti talaktsok tmogatsra.
4.1.1 C-sztring tartalmnak szmm alaktsa
A konverzis fggvnyeket a <cstdlib> deklarlja. A fggvnyek nevnek utols beti a cltpusra
utalnak:
long long atoll( const char *str );
long long strtoll( const char *str, char **str_end, int base );
unsigned long long strtoull( const char *str, char **str_end, int base );
float strtof( const char* str, char** str_end );
long double strtold( const char* str, char** str_end );

A <cinttypes> fejllomnyban tovbbi fggvnyeket tallunk:


intmax_t strtoimax( const char* nptr, char** endptr, int base );
uintmax_t strtoumax( const char* nptr, char** endptr, int base );

38

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


A fenti fggvnyek char tpus karaktereket tartalmaz sztringeket hasznlnak. A <cwchar> s a
<cinttypes> fejllomnyokban megtalljuk az szles karakterekbl ll sztingeket talakt fggvnyeket: wcstoll(), wcstoull(), wcstof(), wcstold(), wcstoimax(), wcstoumax().
4.1.2 A string tpus s a numerikus adatok kztti talaktsok
A <string> fejllomny egy sor konverzis fggvnyt biztost a cmben jelzett talaktsok elvgzsre. Sztringet egyszeren szmm alakthatunk:
int stoi( const string& str, size_t *pos = 0, int base = 10 );
long stol( const string& str, size_t *pos = 0, int base = 10 );
long long stoll( const string& str, size_t *pos = 0, int base = 10 );
unsigned long stoul( const string& str, size_t *pos = 0, int base = 10 );
unsigned long long stoull( const string& str, size_t *pos=0, int base=10 );
float stof( const string& str, size_t *pos = 0 );
double stod( const string& str, size_t *pos = 0 );
long double stold( const string& str, size_t *pos = 0 );

A to_string() fggvnynek vltozatai gyors konverzis lehetsget biztostanak az egyszer C++ numerikus tpusok string tpus sztringg val talaktshoz. Szles sztringg (wstring) a to_wstring()
fggvnyekkel alakthatjuk a szmokat.
4.1.3 Unicode karakterek s sztringek talaktsa
A <cuchar> fejllomnyban deklarlt fggvnyek a 16- s 32-bites szles karakterek (c16, c32) valamint a nullavg sztringben trolt, tbbbjtos (mb) karakterek kztti konverzik elvgzsre szolglnak:
mbrtoc16(), c16rtomb(), mbrtoc32(), c32rtomb()

A <locale> fejllomnyban tallhat wstring_convert<> osztlysablont egytt hasznlva a <codecvt>


fjlban definilt codecvt_utf8<> s codecvt_utf16<> konverzis lersokkal (facet) UTF-8 s UTF-16
kdols sztringet 2- vagy 4-bjtos UCS (unicode) kdols karaktersorozatt alakthatunk. A
codecvt_utf8_utf16<> sablonnal a ktfle UTF kdols kztt konvertlhatunk. Az talakts lpseit
az albbi plda szemllteti:
#include <iostream>
#include <string>
#include <locale>
#include <codecvt>
using namespace std;
int main() {
string utf8 = u8"gk:\U0001D11E pi:\u03C0";
wstring_convert<codecvt_utf8<char16_t>, char16_t> ucs2conv;
u16string ucs2 = ucs2conv.from_bytes(utf8);
cout << ucs2.size() << " darab karakter" << endl;
for (auto p = begin(ucs2); p!=end(ucs2); ++p)
cout << hex << showbase << *p << endl;
}
A program futsnak eredmnye:

9 darab karakter
0x67
0x6b
0x3a
0xd11e
0x20
0x70
0x69
0x3a
0x3c0

39

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


A kvetkez pldban a konverzikat binris fjlbl trtn olvass sorn alkalmazzuk:
#include <fstream>
#include <iostream>
#include <string>
#include <locale>
#include <codecvt>
using namespace std;
void FajlbaIras() {
// UTF-16le adatok (little-endian)
char16_t utf16le[] = u"gk:\U0001D11E, pi:\u03C0"
ofstream fout("adatok.dat");
fout.write( reinterpret_cast<char*>(utf16le), sizeof utf16le);
fout.close();
}
int main() {
FajlbaIras();
wifstream fin("adatok.dat", ios::binary);
fin.imbue(locale(fin.getloc(),
new codecvt_utf16<wchar_t, 0x10ffff, little_endian>));
for (wchar_t ch; fin.get(ch); )
cout << showbase << hex << ch << endl;
fin.close();
}

Mindkt megoldsban elveszett a violin kulcs karaktere, hisz az talakts 16-bites UCS2 kdolsra
trtnt.
4.1.4 j matematikai fggvnyek
A C++11 kibvti a matematikai fggvnyek sort, s mindhrom vals tpushoz biztostja a megfelel
tlterhelt vltozatot <cmath>:
Fggvny
acosh(x)
asinh(x)
atanh(x)
cbrt(x)
copysign(x,y)
erf(x)
erfc(x)
exp2()

Lers
rkusz-koszinusz hiperbolikus fggvny.
rkusz-szinusz hiperbolikus fggvny.
rkusz-tangens hiperbolikus fggvny.
Kbgykfggvny.
A visszaadott rtk x abszolt rtke, eljele pedig megegyezik y eljelvel.
Hibafggvny.
Kiegszt hibafggvny.
2 hatvnya (y=2x)

ex-1 fggvny rtke.


fdim(x,y)
A kt argumentum pozitv klnbsgnek szmtsa (=fmax(x-y,0))
fma(x,y,z)
x*y+z fggvny rtke.
fmax()
A kt argumentum kzl a nagyobb rtkvel tr vissza.
fmin()
A kt argumentum kzl a kisebb rtkvel tr vissza.
fpclassify(x)
Minsti az argumentum rtkt (NaN, normalizlt, vgtelen stb.)
hypot(x,y)
Derkszg hromszg befogihoz tartoz tfog kiszmtsa.
ilogb(x)
A kettes szmrendszerben brzolt lebegpontos szm kitevje egszknt.
isfinite(x)
true rtkkel tr vissza, ha az argumentum vges.
isgreater(x,y)
x > y?
isgreaterequal(x,y)x y?
isinf(x)
true rtkkel tr vissza, ha az argumentum vgtelen.
isless(x,y)
x < y?
expm1(x)

40

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


islessequal(x,y)
islessgreater(x,y)
isnan(x)
isnormal(x)
isunordered(x,y)
lgamma(x)
llrint()
llround()
log1p(x)
log2(x)
logb()
lrint()
lround()
nan(str)
nanf(str)
nanl(str)
nearbyint(x)
nextafter(x,y)
nexttoward(x,y)
remainder(x,y)
remquo(x,y,p)
rint(x)
round(x)
scalbln(x,n)

x y?
x < y vagy x > y?
true rtkkel tr vissza, ha az argumentum nem szm (NaN).
true rtkkel tr vissza, ha az argumentum normalizlt.
Nem sszehasonlthat?
A gamma-fggvny abszolt rtknek termszetes alap logaritmusa.
Kerekts a legkzelebbi egszre (long long tpussal tr vissza).
Kerekts a nulla felli legkzelebbi egszre (long long tpussal tr vissza).
1+x termszetes alap logaritmusa.
Kettes alap logaritmus.
A kettes szmrendszerben brzolt lebegpontos szm kitevje valsknt.
Kerekts a legkzelebbi egszre (long tpussal tr vissza).
Kerekts a nulla felli legkzelebbi egszre (long tpussal tr vissza).
Az NAN (nem szm) rtkkel tr vissza.
Az NAN (nem szm) rtkkel tr vissza.
Az NAN (nem szm) rtkkel tr vissza.
Az argumentum kerektse egsz rtkre a belltott kerektsi md alapjn.
Megadja a kvetkez brzolhat rtket (y irnyban).
Mint a nextafter(), azonban y long double tpus
Kiszmolja az osztsi maradkot.
Mint a remainder(), azonban a hnyadost is visszaadja (p mutat).
int rtkre kerekt, azonban hibt hoz ltre, ha az eredmny klnbzik az argumentumtl.
Kerekts int tpus egszre.

scalbn(x,n)

x * FLT_RADIXn (n egsz)
true rtkkel tr vissza, ha az argumentum negatv.
Gamma-fggvny.
Kerekts a legkzelebbi egszre, nulla irnyban.

signbit(x)
tgamma(x)
trunc(x)

x * FLT_RADIXn (n egsz)

A <cstdlib> s a <cinttypes> fejllomnyok nagymret egsz szmokkal alkalmazhat mveleteket


deklarlnak:
long long abs( long long n );
long long llabs( long long n );
intmax_t abs( intmax_t n );
intmax_t imaxabs( intmax_t n );
lldiv_t div( long long x, long long y );
lldiv_t lldiv( long long x, long long y );
imaxdiv_t div( intmax_t x, intmax_t y );
imaxdiv_t imaxdiv( intmax_t x, intmax_t y );

4.1.5 A bvtett complex osztlysablon


A hagyomnyos C++ complex<> tpus tovbbi tagfggvnyekkel bvlt ( <complex> fejllomny):
proj(z)
asin(z), acos(z), atan(z)
asinh(z), acosh(z), atanh(z)

megadja az argumentum komplex szm vetlett a Riemann gmbn,


az argumentum rkusz szgfggvnyeinek szmtsa,
az argumentum rkusz hiperbolikus szgfggvnyeinek meghatrozsa.

4.1.6 Fordts idej racionlis aritmetika


A ratio<> osztlysablon (<ratio>) egy jl definilt fordtsidej interfszt biztost a trtekkel vgzett
mveletekhez. A ratio<> sablon els paramtere a trt szmllja (num), mg a msodik a trt nevezje(den) lesz. A num s a den a ltrejv osztly statikus adattagjai.

41

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


A megolds rdekessge, hogy a mveleteket is tpusok (osztlysablonok) valstjk meg. A ngy
alapmvelet: ratio_add<>, ratio_subtract<>, ratio_multiply<> s ratio_divide<>. Ugyancsak osztlysablonokat hasznlhatunk az sszehasonltsok elvgzsre: ratio_equal<>, ratio_not_equal<>, ratio_less<>, ratio_less_equal<>, ratio_greater<> s ratio_greater_equal<>.
Nhny elre definilt tpus lefedi a szoksos egysgeknek megfelel trtszmokat:
Tpus
yocto
zepto
atto
femto
pico
nano
micro
milli
centi
deci
deca
hecto
kilo
mega
giga
tera
peta
exa
zetta

Definci
ratio<1,1000000000000000000000000>
ratio<1,1000000000000000000000>
ratio<1,1000000000000000000>
ratio<1,1000000000000000>
ratio<1,1000000000000>
ratio<1,1000000000>
ratio<1,1000000>
ratio<1,1000>
ratio<1,100>
ratio<1,10>
ratio<10,1>
ratio<100,1>
ratio<1000,1>
ratio<1000000,1>
ratio<1000000000,1>
ratio<1000000000000,1>
ratio<1000000000000000,1>
ratio<1000000000000000000,1>
ratio<1000000000000000000000,1>

Lers
-24
10 *
-21
10 *
-18
10
-15
10
-12
10
-9
10
-6
10
-3
10
-2
10
-1
10
+1
10
+2
10
+3
10
+6
10
+9
10
+12
10
+15
10
+18
10
+21
10 *

A csillaggal jelzett tpusok megvalstsa opcionlis, csak akkor lteznek, ha az <cstdint> intmax_t
tpusa lefedi a szmll s a nevez rtkeit.
#include <iostream>
#include <ratio>
using namespace std;
int main()
{
typedef ratio<3,7> tort1;
typedef ratio<6,21> tort2;
typedef ratio_add<tort1, tort2> tort3;
cout << tort3::num << '/' << tort3::den << endl;
if (ratio_less<tort1, tort2>::value)
cout << "3/7 < 6/21\n";
else
cout << "3/7 >= 6/21\n";
constexpr int kg=123;
constexpr int gramm = ratio_divide<ratio<kg,1>, milli>::num;
cout << "123 kg = " << gramm << " gramm" << endl;
}
A program futsnak eredmnye:

42

5/7
3/7 >= 6/21
123 kg = 123000 gramm

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


4.2 Vletlen szmok ellltsa
A <random> fejllomny osztlysablonok sorval segti a vletlen szmok klnbz mdszerrel trtn ellltst. A tbbfle megolds elrshez kln ki kell vlasztanunk egy vletlen szm motort
(engine), egy eloszlst (distribution), melyeket aztn sszekapcsolva elll a vletlen szm genertor.
A vletlen szm motor valamilyen algoritmus alapjn lltja el a szmokat. A <random> tbb motort
is tartalmaz:
linear_congruential_engine<>
lineris kongruens algoritmus (mint a rand() esetn),
mersenne_twister_engine<>
Mersenne twister algoritmus,
subtract_with_carry_engine<>
kivons tvitellel algoritmus.
A motorokhoz adaptcik is tartoznak, amelyek valamilyen szempont szerint mdostjk a megadott
alapmotor mkdst:
discard_block_engine<>, independent_bits_engine<>, shuffle_order_engine<>
Mivel az motorok s az adaptciik helyes paramterezse nem egyszer feladat, a fejllomny elre
felparamterezett motorokat is a rendelkezsnkre bocsjt: seed_seq<>, minstd_rand, mt19937,
ranlux24, knuth_b, default_random_engine stb.
Mg nagyobb az eloszlsok vlasztka. Szmtalan uniform, Bernoulli, Poisson, norml vagy mintavteles eloszls kzl vlaszthatunk csak nhny zeltl:
uniform_int_distribution<>, bernoulli_distribution<>, poisson_distribution<>,
normal_distribution<>, discrete_distribution<>
A defincik alkalmazst az albbi pldaprogram szemllteti:
#include <random>
#include <iostream>
#include <ctime>
using namespace std;
int main() {
mt19937 motor;
motor.seed(time(nullptr)); // a generl algoritmus inicializlsa
double kozepertek = 2.5, szoras = 1;
// Klnbz eloszlsok ksztse:
// alaprtelmezett intervallum [0, MAX]
uniform_int_distribution<uint32_t> uintEloszlas;
// intervallum [0,10]
uniform_int_distribution<uint32_t> uintEloszlas10(0,10);
// N(kzprtk, szrs)
normal_distribution<double> normalEloszlas(kozepertek, szoras);
// vletlen szmok ellltsa:
for (int i=0; i<10; i++) {
cout << uintEloszlas(motor) << '\t'
<< uintEloszlas10(motor) << '\t'
<< normalEloszlas(motor) << endl;
}
}

43

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse

A program futsnak eredmnye:

4097594794
3284206494
1585982901
2813963803
2881504895
3379910637
431323802
3496590794
661944248
2108095663

5
6
2
3
8
9
8
9
3
8

0.71713
3.34636
2.85585
0.601554
2.89266
1.56064
1.85685
3.89834
2.57102
3.01404

Mg egy fontos ok, ami miatt inkbb a <random> knyvtrat hasznljuk a hagyomnyos rand() fggvny helyett. Az j eszkzkkel a vletlen szmok generlsa szlbiztos: vagy minden szl sajt loklis
motort alkalmaz, vagy egy kzs motorobjektumot rnek el szinkronizlva.
4.3 Id- s dtumkezels
A C++11 j idmodellel segti a programok s a szlak idkezelsi feladatait. A modell alapelemei az
rk (clocks), amelyek meghatrozzk az idszmts kezdett (epoch, pl. 1970. janur 1.) valamint az
ratsek gyakorisgt (vagyis az ra pontossgt, pl. 1 ms). Az raosztlyokat a <chrono> fejllomny beptst kveten a chrono nvtrben rjk el:
chrono::system_clock
a rendszer ltal hasznlt vals idej ra (bellthat),
chrono::high_resolution_clock a rendszerben fellelhet legpontosabb ra (bellthat),
chrono::steady_clock
pontos idmrshez jl hasznlhat monoton ra, amely
nem llthat be.
A msik fontos eleme az idkezelsnek az idtartam (duration), amely adott idegysgek szmt
jelli. Az idtartamot a chrono::duration<> osztlysablon kpviseli, melyet a ratio<> sablonnal egytt
hasznlva sajt idtartamegysgeket is kszthetnk, az elre definiltakon (chrono::nanoseconds,
chrono::microseconds, chrono::milliseconds, chrono::seconds, chrono::minutes, chrono::hours) tlmenen. (A msodperc az alaprtelmezett idtartam egysg.)
#include <chrono>
#include <iostream>
using namespace std;
using namespace chrono;
int main() {
typedef duration<int, ratio<1,2>> felmasodperc; // flmsodperc
felmasodperc d1(10);
seconds d2 = duration_cast<seconds>(d1);
cout << "a megadott id: " << d2.count() << " mp" << endl; // 5 mp
}

A duration<> sablon els paramtere az ratemek szmt trol tpus, mg a msodik a msodpercekhez kpest definilja az idtartamegysget. Az idegysgek szmt az idtartam osztly count()
tagfggvnyvel krdezhetjk le, mg a klnbz idtartamok kztti tvltshoz a
duration_cast<>() fggvnysablont kell hasznlnunk.
Az idtartam osztly tovbbi statikus tagjaival lekrdezhetjk az idtartamhoz tartoz nulls, minimlis s maximlis rtket:
cout << seconds::zero().count()<< endl; // 0
cout << seconds::min().count() << endl; // -9223372036854775808
cout << seconds::max().count() << endl; // 9223372036854775807

44

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


Az idtartam objektumokkal hasznlhatjuk az rtkadst (=), az t alapmveletet (+, -, *, /, %) (sszetett rtkadsban is) valamint az sszehasonlt mveleteket (==, !=, <, <=, >, >=). Felhvjuk a figyelmet arra, hogy a szorzs, oszts s maradkkpzs esetn csak az egyik operandus lehet idtartam, a
msik operandusnak szmnak kell lennie!
minutes
m3 += 5
cout <<
cout <<

m1(3), m2(6),
* m1 - m2 / 2
m3.count() <<
(m3 <= m1) <<

m3(-1);
+ m1 % 2;
endl; // 12
endl; // 0

Az idmodell harmadik pillre az idpont (timepoint), amelyet a chrono::time_point<> osztlysablon


valst meg. Az idpont valjban az ra idszmtsnak kezdett s az eltelt idtartamot kombinlja. A Unix/Linux rendszerekben a rendszerra ltal visszaadott beptett idpontok:
system_clock::time_point tp;
tp = system_clock::time_point::min();
tp = system_clock::time_point::max();

Thu Jan 1 01:00:00 1970


Sat Mar 5 17:27:38 1904
Mon Oct 29 06:32:22 2035

Idpont objektumot tbbflekppen is ltrehozhatunk. Hasznlhatjuk az ra osztlyba ptett


time_point tpust, vagy magt a time_point<> sablont. Els esetben a trolt idtartam msodperc
lesz, mg msodik esetben ez szabadon megadhat, az albbi pldban lthat mdon:
#include <chrono>
#include <iostream>
#include <ctime>
#include <string>
using namespace std;
using namespace chrono;
string Idopont2Str (const system_clock::time_point& tp) {
// az idpont talaktsa time_t tpus idv:
time_t t = system_clock::to_time_t(tp);
string ts = ctime(&t);
ts.resize(ts.size()-1); // az jsor karakter trlse
return ts;
}
int main() {
// a most lekrdezse klnbz mdon:
system_clock::time_point most1 = system_clock::now();
time_point<system_clock> most2 = most1;
time_point<system_clock, milliseconds> most_ms;
most_ms = time_point_cast<milliseconds>(most2);
cout << Idopont2Str(most1) << endl;
// 7 nap 12 perc 23 msodperc mlva:
seconds kesobb = duration_cast<seconds>(7*hours(24) +
minutes(12) + seconds(23));
most1 += kesobb;
most2 = most2 + kesobb;
most_ms += kesobb;
cout << Idopont2Str(most1) << endl;
}
A program futsnak eredmnye:

Sat Sep 21 17:25:57 2013


Sat Sep 28 17:38:20 2013

Az idpont objektumokhoz tartoz +, += s -, -= mveletekkel az idpontot a megadott idtartammal


mdosthatjuk, s az idpontokat ssze is hasonlthatjuk (==, !=, <, <=, >, >=).

45

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


Az j idmodell nem rendelkezik humn interfsszel, nem ismeri a naptrunkat. Az rk to_time_t()
tagfggvnye a hagyomnyos C idkezelshez time_t tpusv alaktja az idpontot. (Ezt alkalmaztuk az elz plda Idopont2Str() fggvnyben a megjelentshez). A from_time_t() tagfggvnynyel pedig konkrt idpontot is megadhatunk. Az kvetkez pldaprogram megmondja, hogy hnyat
kell mg Karcsonyig aludnunk:
#include <chrono>
#include <ctime>
#include <iostream>
using namespace std;
using namespace chrono;
int main() {
tm xmas1 = {0};
xmas1.tm_year = 2013-1900;
xmas1.tm_mon = 12-1;
xmas1.tm_mday = 25;
time_t xmas2 = mktime(&xmas1);
system_clock::time_point xmas3 = system_clock::from_time_t(xmas2);
system_clock::time_point most = system_clock::now();
typedef duration<int, ratio<24*3600,1>> nap;
nap napok = duration_cast<nap>(xmas3-most);
cout << "meg aludni kell: " << napok.count() << " napot.\n"; // 94
}

Vgezetl nzznk egy egyszer futsidt mr programot, amelyben megmrjk, hogy mennyi id
szksges 10 milli elemet tartalmaz vektor rendezshez!
#include <iostream>
#include <chrono>
#include <vector>
#include <algorithm>
using namespace std;
using namespace chrono;
int main() {
const int meret = 10000000;
vector<int> v(meret);
srand(unsigned(time(nullptr)));
for_each (begin(v), end(v), [](int& e) { e = rand();});
random_shuffle(begin(v), end(v));
auto start = high_resolution_clock::now();
sort(begin(v), end(v));
auto stop = high_resolution_clock::now();
auto eltelt = duration_cast<milliseconds>(stop - start);
cout << "mrt id: " << eltelt.count() << " ms" << endl; // 748 ms
}

4.4 Regulris kifejezsek knyvtra


A C++11 az STL filozfijnak megfelelen osztlysablonok s fggvnysablonok segtsgvel valstja
meg a regulris kifejezst kezelst. Az alaposztlyok (basic_regex, sub_match, match_results)
mellett algoritmusok (regex_match, regex_search, regex_replace), itertorok (regex_iterator,
regex_token_iterator) valamint elre definilt konstansok (std::regex_constants nvtr) segtik a
munknkat.
A basic_regex sablon char s a wchar_t tusokkal specializlt vltozatait (regex, wregex) hasznljuk a
szablyos kifejezsek trolsra:

46

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


regex szo("[[:alpha:]]+");
regex szokozok("[[:space:]]*(.+)", regex::extended);

A regulris kifejezsek megadsnl hromfle szablygyjtemny kzl is vlaszthatunk. Az alaprtelmezett az ECMAScript (ECMA-262, JavaScript, Perl 5) szintaxis, azonban a msodik argumentumban a POSIX alap (basic) s bvtett (extended) nyelvtannak elkalmazst is krhetjk.
A kvetkez pldaprogram a megadott sztringrl megllaptja, hogy egsz szmot tartalmaz-e vagy
sem:
#include <iostream>
#include <regex>
#include <string>
using namespace std;
int main() {
string input;
regex egesz("(\\+|-)?[[:digit:]]+");
while (true) // A q billentylenyomsig inputot vr
{
cout<<"Krek egy egsz szmot!"<<endl;
cin>>input;
if ( input == "q" )
break;
if ( regex_match(input, egesz) )
cout << "egsz" << endl;
else
cout << "hibs input" << endl;
}
}

Amennyiben a C++ nyelv vals szmformtumnak megfelel adatokat szeretnnk ellenrizni, az


albbi regulris kifejezst kell hasznlnunk:
regex valos("((\\+|-)?[[:digit:]]+)(\\.(([[:digit:]]+)?))?((e|E)"
"((\\+|-)?)[[:digit:]]+)?");

Bizonyos mveletek esetn a match_results osztlysablon karakteres specializlt vltozatai (cmatch,


wcmatch, smatch, wsmatch) troljk az egyeztets eredmnyt.
Az albbi pldban regulris kifejezsek segtsgvel egy sztringbl eltvoltjuk a bevezet szkzket, illetve sztvlogatjuk a benne trolt szavakat s szmokat:
#include <iostream>
#include <string>
#include <regex>
using namespace std;
int main() {
regex egesz("(\\+|-)?[[:digit:]]+");
regex szo("[[:alpha:]]+");
regex szokozok("[[:space:]]*(.+)");
// A bevezet szkzk eltvoltsa
string input ="
Ivan9 Anna23 Adrienn26 Aliz33";
smatch eredmeny;
regex_search(input, eredmeny, szokozok);
cout << eredmeny[1].str() << endl;
// Sztvlasztja az inputbl a neveket s a szmokat
const string formatum =""; // helyettest formtumsztring

47

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


string szavak, szamok;
szamok = regex_replace(eredmeny[1].str(), egesz, formatum,
regex_constants::format_default);
szavak = regex_replace(eredmeny[1].str(), szo, formatum,
regex_constants::format_default);
cout << szavak << endl;
cout << szamok << endl;
}
A program futsnak eredmnye:

Ivan9 Anna23 Adrienn26 Aliz33


9 23 26 33
Ivan Anna Adrienn Aliz

4.5 Kibvtett tpuskezel knyvtr


A C++ tpuskezel knyvtr jabb alaptpusokkal (<cstddef>), illetve a tpusok fordtsidej
(<type_traits>) s futsidej (<typeindex>) kezelst segt sablonokkal bvlt.
A tpusjellemzk fordts kzbeni ellenrzst segtik az is_void<>, is_integral<>, is_class<>,
is_copy_constructible<> stb. sablonok (<type_traits>)
#include <type_traits>
#include <iostream>
#include <algorithm>
#include <limits>
using namespace std;
template <typename T>
T Lkt(const T& a, const T& b) {
static_assert(is_integral<T>::value,
"T-nek egsz tpusnak kell lennie!");
for (int lkt = max(a, b); lkt<=a*b; lkt++)
if (lkt%a==0 && lkt%b==0) return lkt;
}
int main() {
cout << numeric_limits<int>::lowest() << endl;
cout << Lkt(12,8) << endl;
// 24
cout << Lkt(12.3,7.8) << endl;
// fordtsi hiba
}

Ugyancsak itt tallunk egy sor tpuskszt s -talakt sablont: integral_constant<>, add_const<>,
result_of<> stb.
A futs kzbeni tpusazonostst segti a tpusokhoz rendezett indexsort rendel type_index osztly
(<typeindex>):
#include <iostream>
#include <typeinfo>
#include <typeindex>
#include <unordered_map>
#include <string>
using namespace std;
class A {
public:
virtual ~A() {}
};

48

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


int main() {
unordered_map<type_index, string> tipusNevek;
tipusNevek[type_index(typeid(int))] = "egsz";
tipusNevek[type_index(typeid(double))] = "vals";
tipusNevek[type_index(typeid(A))] = "A osztly";
int i;
double d;
A a;
cout << "i tpusa " << tipusNevek[type_index(typeid(i))] << endl;
cout << "d tpusa " << tipusNevek[type_index(typeid(d))] << endl;
cout << "a tpusa " << tipusNevek[type_index(typeid(a))] << endl;
}

4.6 Polimorf fggvnyobjektumok


A fggvnyobjektumok olyan objektumok, amelyekben definilt a fggvnyhvs opertora. A C++
tbb knyvtri fggvnyobjektummal rendelkezik, azonban az ilyen objektumok ltrehozst s kezelst is segti. A C++11 sok j elemmel (function<>, bind<> stb.) bvti a <functional> fejllomny
definciit, azonban tbb elemet (unary_function<>, binder1st<> stb.) elavultnak nyilvnt.
A hash<> sablon specializlt vltozatai az alaptpusokhoz s a karaktersorozat knyvtri tpusokhoz
hash (hast) kdot szmtanak.
#include <iostream>
#include <functional>
#include <string>
using namespace std;
int main() {
hash<string> hashFv;
string str = "C++ programozsi nyelv";
size_t hashKod = hashFv(str);
cout << hashKod << '\n';
// 4265739948
}

A template< class R, class... Args > class function<R(Args...)>; deklarls funtion<> sablon egy ltalnos cl fggvnyburkol (function wrapper), amellyel norml fggvnyekre, tagfggvnyekre,
lambda fggvnyekre valamint funktorokra egyarnt hivatkozhatunk. (Funktor functor olyan osztly, amely definilja a fggvnyhvs opertort.)
#include <iostream>
#include <functional>
using namespace std;
int Kerekit(double x) {
return int(x+0.5);
}
class A {
public:
long Levag(double x) { return long(x);}
};
class Funktor {
public:
long operator()(double x) const {
return (long)x;
}
};

49

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


int main() {
function<int(double)> kerekitHivas = &Kerekit;
cout << kerekitHivas(12.7) << endl;
// 13
A a;
function<long(A&, double)> levagHivas = &A::Levag;
cout << levagHivas(a, 2.9) << endl;
// 2
function<long(A*, double)> levagHivasPtr = &A::Levag;
cout << levagHivasPtr(&a, 2.9) << endl;
// 2
function<long(long a)> Kob = [](long x){ return x*x*x; };
cout << Kob(10)<< endl;
// 1728
auto Negyzet = [](long x){ return x*x; };
cout << Negyzet(10) << endl;
// 144
Kob = Negyzet;
Funktor fu;
function <long(double)> fuHivas = fu;
cout << fuHivas(12.34) << endl;

// 12

A mem_fn<> sablon szintn fggvnyburkol objektumot kszt, azonban egy megadott tagfggvny
mutat alapjn.
#include <iostream>
#include <functional>
using namespace std;
class A {
public:
long Levag(double x) { return long(x);}
};
int main() {
A a;
auto levagFv = mem_fn(&A::Levag);
cout << levagFv(a, 12.7) << endl;
}

// 12

A function objektum rendelkezik a bool tpusra konvertl opertorral, mely mvelet eredmnybl
megtudhatjuk, hogy a fggvnyburkol kapott-e rtket:
#include <iostream>
#include <functional>
using namespace std;
int main () {
function<void()> f;
cout << (bool) f << endl;
f = [](){};
cout << (bool) f << endl;
}

// 0
// res lambda fggvny!
// 1

A bind<> fggvny segtsgvel argumentumokat kthetnk a fggvnyobjektumokhoz. A ref<> s


cref<> sablonok reference_wrapper tpus argumentumokat kszthetnk.
Az albbi pldban a bind<> s a helyfoglal objektumok (_1, _2, ) segtsgvel az argumentumokat
klnbz sorrendben tovbbtjuk a hvott fggvnynek:
#include <functional>
#include <string>
#include <iostream>

50

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


using namespace std;
using namespace std::placeholders;
void Kiir(string a, string b, string c) {
cout << a << " " << b << " " << c << endl;
}
int main() {
auto fa = bind(Kiir, _1, _2, _3);
auto fb = bind(Kiir, _3, _1, _2);
auto fc = bind(Kiir, "delta", _1, _1);
fa("alfa", "beta", "gamma");
fb("alfa", "beta", "gamma");
fc("alfa", "beta");
}
A program futsnak eredmnye:

alfa beta gamma


gamma alfa beta
delta alfa alfa

A bind<> fggvnnyel egytt hasznljuk a ref<> s a cref<> sablonokat, amelyekkel a hvni kvnt
fggvnyhez referencia, illetve konstans referencia tpus argumentumokat kthetnk:
#include <functional>
#include <iostream>
using namespace std;
void Fv(int& a, int& b, const int& c) {
cout << "Fggvnyen bell: " << a << ' ' << b << ' ' << c << endl;
++a, ++b;
}
int main() {
int a = 1, b = 2, c = 3;
function<void()> fvHivas = bind(Fv, a, ref(b), cref(c));
a = 10, b = 20, c = 30;
cout << "Fv hvsa eltt: " << a << ' ' << b << ' ' << c << endl;
fvHivas();
cout << "Fv hvsa utn: " << a << ' ' << b << ' ' << c << endl;
}
A program futsnak eredmnye:

Fv hvsa eltt: 10 20 30
Fggvnyen bell: 1 20 30
Fv hvsa utn: 10 21 30

4.7 Inicializl lista sajt osztlyokban


Az inicializl lista feldolgozsa sorn a fordt a sablonhvsban megadott tpus adatokbl egy
tmbt llt el, amelyhez kapcsolt objektum rendelkezik a size(), begin() s end() tagfggvnyekkel.
Az initializer_list<> tpus objektumokat nllan is felhasznlhatjuk a programokban:
#include <iostream>
#include <initializer_list>
using namespace std;
void Kiir(const initializer_list<int>& il) {
for (int x : il) cout << x << ' '; cout << endl;
cout << "Elemek szama: " << il.size() << endl;
}

51

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


int main() {
initializer_list<int> uresLista;
Kiir(uresLista);
Kiir({});
initializer_list<int> egeszek1 {12, 23, 34, 45};
Kiir(egeszek1);
auto egeszek2 = {120, 230, 340, 450};
Kiir(egeszek2);
Kiir({1, 2, 3, 4, 5, 6});
}
A program futsnak eredmnye:
Elemek szama: 0
Elemek szama: 0
12 23 34 45
Elemek szama: 4
120 230 340 450
Elemek szama: 4
1 2 3 4 5 6
Elemek szama: 6

Az osztlyaikat egyszeren ellthatjuk inicializl listval. Mindssze egy olyan konstruktort kell ksztennk, amely egy initializer_list<> tpus paramterrel rendelkezik:
#include <iostream>
#include <initializer_list>
#include <memory>
using namespace std;
template<typename T>
class Vektor {
T* adatok;
int meret;
public:
Vektor(initializer_list<T> lista) {
meret = (int)lista.size();
adatok = new T[meret];
uninitialized_copy(begin(lista), end(lista), adatok);
}
~Vektor() { delete []adatok; }
void Kiir() {
for (int i=0; i<meret; i++)
cout << adatok[i] << " ";
cout << endl;
}
};
int main() {
Vektor<int> v {1,2,3,4,5};
v.Kiir();
}

Felhvjuk a figyelmet arra, hogy az egyszer konstruktorhvsokban is alkalmazhatunk inicializl


listt, amelynek feldolgozsa, s a konstruktorhvs elvgzse a fordt feladata. Az ilyen listk akr
klnbz tpus elemeket is tartalmazhatnak:
#include <iostream>
#include <string>
using namespace std;

52

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


struct Adatok {
int ma;
double mb;
string ms;
Adatok(int a=0, double b=0.0, string s="") {
ma=a; mb=b; ms = s;
}
};
int main() {
Adatok a1(12), a2 = {12}, a3 {12};
Adatok b1(12, 23.4), b2 = {12, 23.4}, b3 {12, 23.4};
Adatok c1(12, 23.4, "C++");
Adatok c2 = {12, 23.4, "C++"};
Adatok c3 {12, 23.4, "C++"};
}

C++11

C++98

4.8 Vltozsok a kontnerek (trolk) knyvtrban


A C++11 szabvnyos sablontra tbb j trolval egszti ki a mr jl bevlt kontnereket. Az albbi
tblzatban sszefoglaltuk a hagyomnyos s az j trol osztlysablonokat:
Szekvencilis trolk
vector dinamikus, folytonos trols tmb,
deque ktvg sor,
list ktszeresen lncolt lista.

Asszociatv trolk
set rendezett halmaz egyedi kulcsokkal,
map rendezett sztr egyedi kulcsokkal,
multiset rendezett halmaz,
multimap rendezett sztr.

array folytonos trols statikus tmb,


forward_list egyszeres lncols lista.

unordered_set hastott halmaz egyedi kulcsokkal,


unordered_map hastott sztr egyedi kulcsokkal,
unordered_multiset hastott halmaz,
unordered_multimap hastott sztr.

Az array<> tpus a C-stlus egydimenzis tmbk kezelsnek egyszersgt tvzi a kontnerek


hasznos tulajdonsgaival:
#include <array>
#include <iostream>
using namespace std;
int main() {
array<int,5> a = {1,2,3};
array<int,5> b;
b = a;
for (int i=0; i<b.size(); i++)
cout << b[i] << ' ';
}

// msols
// mret lekrdezse
// 1 2 3 0 0

Tbbdimenzis tmbk esetn szintn a C-stlus megoldshoz hasonl mdon jrhatunk el, pldul
2x3-as mtrix esetn:
array<array<int,3>, 2> m;
for (int i=0; i<m.size(); i++)
// sorok
for (int j=0; j<m[i].size(); j++) // oszlopok
m[i][j]=i+j;
0
1

1
2

2
3

53

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


A forward_list<> gyors, egyirny listakezelst valst meg. A listba val beszrshoz, illetve a trlshez az elemek szmtl fggetlen id szksges. Az albbi pldaprogramban rviden sszefoglaltuk a listakezels alapvet mveleteit:
#include <forward_list>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <string>
using namespace std;
void ListaKiir(const string& s, const forward_list<int>& lista) {
cout << s << '\t';
copy(lista.cbegin(), lista.cend(),
ostream_iterator<int>(cout," "));
cout << endl;
}

int main() {
// A lista ltrehozsa s feltltse
forward_list<int> lista = { 1, 2, 3, 4 };
ListaKiir ("A kiindul lista:", lista);
// Elem beszrsa a lista elejre
lista.insert_after(lista.before_begin(), 10);
lista.push_front(11);
lista.insert_after(lista.before_begin(), {21,22,23,3,11,12} );
ListaKiir ("8 j elem az elejre:", lista);
// Az els kt elem trlse
lista.erase_after(lista.begin()); // 2. elem
lista.pop_front(); // 1. elem
ListaKiir ("Az els 2 elem trlve:", lista);
// A lista rendezse s az ismtld elemek trlse
lista.sort();
lista.unique();
ListaKiir ("Rendezett, kiegyelt:", lista);
}
A program futsnak eredmnye:

A kiindul lista:
8 j elem az elejre:
Az els 2 elem trlve:
Rendezett, kiegyelt:

1 2 3 4
21 22 23 3 11 12 11 10 1 2 3 4
23 3 11 12 11 10 1 2 3 4
1 2 3 4 10 11 12 23

A szabvnyos C++11 nyelv a korbbi asszociatv kontnerekhez elrhetv tette az elemeket rendezettsg nlkl trol prjukat: unordered_set<>, unordered_multiset<>, unordered_map<> s
unordered_multimap<>.
Mg a C++98 halmaz s sztr objektumai az elemeket binris rendezfban troljk, addig az j
megoldsok hast (hash) tblt alkalmaznak. A kt csoport osztlyainak programozi fellete majdnem teljes egszben megegyezik, mint ahogy az albbi pldban is lthat. Termszetesen az
unordered_xxx<> kontnerek nem rendelkeznek a rendezettsgre pl tagfggvnyekkel (rbegin(),
lower_bound(), value_comp() stb.).
#include <iostream>
#include <unordered_map>
#include <map>
#include <string>
using namespace std;

54

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse

int main() {
unordered_map<string,int> win;
// Elemek bevitele
win["NT"] = 0;
win["XP"] = 1;
win["Vista"] = 6;
win["7"] = 9;
win["8"] = 12;
// A trolt vszmok mdostsa
for (auto p = win.begin(); p != win.end(); ++p)
p->second += 2000;
// Az "NT" tnevezse "2000"-re elemcservel
win["2000"] = win["NT"];
win.erase("NT");
// Az elemek rtk szerint rendezve a multimap-ben
multimap<int, string> winmm;
for (auto p = win.begin(); p != win.end(); ++p)
winmm.insert(pair<int, string>(p->second, p->first));
// Az elemek kirsa
for (auto p = winmm.begin(); p != winmm.end(); ++p)
cout << "Windows " << p->second << " " << p->first << endl;
}
A program futsnak eredmnye:

Windows
Windows
Windows
Windows
Windows

2000 2000
XP 2001
Vista 2006
7 2009
8 2012

Az unordered_xxx<> osztlysablonok argumentumaknt sajt kszts hast (hash) kdot szmt


s azonossgot vizsgl konstans funkcionlt is megadhatunk. Ezzel a mdszerrel sajt tpus adatokat is trolhatunk a rendezs nlkli asszociatv kontnerekben:
#include <functional>
#include <iostream>
#include <unordered_set>
#include <string>
using namespace std;
struct Komplex {
double re, im;
Komplex(double a=0, double b=0) : re(a), im(b) {}
};
struct KomplexEqual {
bool operator()(const Komplex& k1, const Komplex& k2) const {
return (k1.re == k2.re) && (k1.im == k2.im);
}
};
struct KomplexHash {
size_t operator()(const Komplex& k) const {
return hash<double>()(k.re) | hash<double>()(k.im);
}
};

55

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


int main() {
unordered_set<Komplex, KomplexHash, KomplexEqual> komplexSet;
komplexSet.insert(move(Komplex(1,2)));
komplexSet.insert(move(Komplex(2,3)));
komplexSet.insert(move(Komplex(3,1)));
auto p = komplexSet.find(Komplex(2,3));
if (p == komplexSet.end())
cout << "nincs meg" << endl;
else
cout<< p->re << "+i" << p->im << endl;
}

4.8.1 Kezdrtkads a kontnereknek


A C++98 szabvny kontner objektumait csak a konstruktor adta lehetsgekkel, illetve kln tagfggvnyekkel inicializlhatjuk.
vector<int> iv(10,2);
vector<string> sv;
sv.push_back("alfa");
sv.push_back("bta");
sv.push_back("gamma");
map<string, int> m1;
m1["egy"] = 1;
m1["kett"] = 2;
m1.insert(pair<string, int>("hrom", 3));

C++11-ben a kezdrtkads az inicializl lista segtsgvel egyszeren elvgezhet:


vector<int> iv2 = {2, 7, 12, 23, 27, 30};
vector<string> sv2 {"alfa", "bta", "gamma"};
map<string, int> m2 { { "egy", 1}, {"kett", 2}, {"hrom", 3} };

4.8.2 A move szemantika s az STL kontnerek


Az thelyezs (move) szemantika bevezetse minden kontner osztlysablon kibvtst jelentette,
hiszen el kellett ltni ket az thelyez konstruktorral s opertorral. A kontnerekbe j adatot helyez tagfggvnyeknek megjelent a jobbrtk referencival mkd prjuk, pldul, a vector<>
osztlysablon esetn:
void push_back( const T& value );
void push_back( T&& value );

// msol
// thelyez

A <utility> fejllomnyban definilt move fggvnysablon a balrtk hivatkozsokat jobbrtk hivatkozsokk alaktja, gy a msol konstruktor s a msolssal elvgzett rtkads helyett az thelyez
konstruktor s az thelyez rtkad opertor hvdik meg. A megolds clja a sok ideiglenes objektumpldny szmnak cskkentse, gy a programfuts hatkonysgnak nvelse. A move hvs
eredmnye valjban egy xvalue referencia, ami azt jelenti, hogy a fordt az thelyez tagfggvnyek (rvalue) hinyban a megfelel msol tagfggvnyeket (lvalue) hvja.
#include <vector>
#include <complex>
#include <iostream>
using namespace std;
typedef complex<double> komplex;

56

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


const vector<double> valosErtekek (const vector<komplex>& v) {
vector<double> valos( v.size() );
for (auto c : v)
valos.push_back( c.real() );
return move(valos);
}
int main() {
vector<komplex> cv;
for ( int i = 10; i < 1000; i++ )
cv.push_back( move(komplex(i*1.2, i/2.3)));
vector<double> v = valosErtekek ( cv );
}

Az ideiglenes objektumok elkerlsnek msik mdja a kontner osztlyok bvtse az emplace() (az
insert() helyett) s az emplace_xxx() tagfggvnyekkel, amelyek helyben hozzk ltre a troland
objektumot.
#include <iostream>
#include <vector>
#include <complex>
using namespace std;
int main() {
vector<complex<double>> cv { {12,7} };
cv.push_back(complex<double>(12,23));
cv.emplace_back(7,29);
cv.insert(cv.begin(), complex<double> (10,2));
cv.emplace(cv.begin(), 11,30);
for (const auto& c : cv)
cout << c.real() << " + i" << c.imag() << endl;
}
A program futsnak eredmnye:

11 + i30
10 + i2
12 + i7
12 + i23
7 + i29

A msols s az thelyezs az itertorok szintjn is megklnbztethet az <iterator> fejllomnyban


definilt move_iterator<> osztlysablon s a make_move_iterator<>() fggvnysablon segtsgvel.
Ugyancsak itt talljuk meg az itertorokat adott szm elemmel elre (next), illetve visszalptet
(prev) fggvnysablonokat.
#include <iostream>
#include <list>
#include <vector>
#include <string>
#include <iterator>
#include <algorithm>
using namespace std;
void Kiir(const string &s, const vector<string>& vs){
cout << s;
for (const auto e : vs)
cout << "\"" << e << "\" ";
cout << endl;
}

57

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


int main() {
list<string> lsgr{"C++", "Java", "C#"};
vector<string> v1gr(lsgr.begin(), lsgr.end());

// msols

vector<string> v2gr(make_move_iterator(lsgr.begin()),
make_move_iterator(lsgr.end())); // thelyezs
cout << "lsqr tartalma: ";
for (const auto s : lsgr)
cout << "\"" << s << "\" "; cout << endl;
Kiir("v1gr tartalma: ", v1gr);
Kiir("v2gr tartalma: ", v2gr);
typedef vector<string>::iterator tmutato;
string s = accumulate(move_iterator<tmutato>(v1gr.begin()),
move_iterator<tmutato>(v1gr.end()), string());
cout << s << endl;
Kiir("v1gr tartalma: ", v1gr);
}
A program futsnak eredmnye:

lsqr tartalma:
v1gr tartalma:
v2gr tartalma:
C++JavaC#
v1gr tartalma:

"" "" ""


"C++" "Java" "C#"
"C++" "Java" "C#"
"" "" ""

4.8.3 A begin, end s swap fggvnysablonok hasznlata


A C++11 szabvny a tartomnyalap for ciklus mkdshez definilja a begin s az end fggvnysablonokat, amelyek kontnerek esetn a begin() illetve az end() tagfggvnyeket hvjk. A sablonos
megolds elnye, hogy az j osztlyokat egyszeren ellthatjuk a begin s az end hasznlatnak kpessgvek, csupn a sablonokat kell az j tpusra specializlni. A C++11-ben megjelent egy harmadik
fggvnysablon, a swap. A vele elvgezhet felcserls mvelet minden kontner tagfggvnyeknt
is ltezik. (Ezekkel a specializlt sablonokkal a valarray<> tpus objektumok, valamint a hagyomnyos tmbk szintn feldolgozhatk a tartomnyalap for ciklussal.)
A begin, az end s a swap fggvnysablonok tlterhelt vltozatait tbb fejllomny is tartalmazza
(<iterator>, <vector>, <utility> stb.)
A begin s az end fggvnysablonokkal, valamint a tartomnyalap ciklus alkalmazsval a kontnerekben trolt adatok feldolgozsa tbbflekppen elvgezhet. Pldaknt tekintsk az egyirny
listt, amely nem rendelkezik az indexels opertorval, gy az elemek elrshez ltalban
itertorokat hasznlunk:
#include <forward_list>
#include <iterator>
#include <iostream>
using namespace std;
int main() {
forward_list<int> fl {12, 7, 23, 10, 2};
}

Az elemek megjelentse a C++98 ltal is tmogatott egyetlen megoldst alkalmazva:


forward_list<int>::iterator flp;
for (flp = fl.begin(); flp != fl.end(); flp++)
cout << *flp << endl;

58

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


Az automatikus tpusads s a begin s end sablonok segtsgvel a megolds sokkal bartsgosabb
vlik:
for (auto flp = fl.begin(); flp != fl.end(); flp++)
cout << *flp << endl;
for (auto flp = begin(fl); flp != end(fl); flp++)
cout << *flp << endl;

A tartomnyalap ciklus alkalmazsval az itertorokrl is megfeledkezhetnk:


for (const auto& listaElem : fl)
cout << listaElem << endl;

4.9 Kibvtett algoritmus knyvtr


A move szemantika bevezetse az algoritmusoknl szintn vltozsokat hozott. A mr korbban meglv fggvnysablonok mvelet paramternek fggvnymutatt s thelyez vagy msol konstruktorral rendelkez (move constructible) fggvnyobjektumot (lambda vagy funktor) is tadhatunk.
Az albbi pldban a for_each() algoritmussal szemlltetjk a lehetsgeket:
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
void Add5(int & n) { n += 5; }
struct Osszeg {
Osszeg() { osszeg = 0; }
void operator()(int n) { osszeg += n; }
int osszeg;
};
int main() {
vector<int> v{3, -2, 26, 8, 19, 25, 6, 7};
for_each( v.begin(), v.end(), Add5 );
for_each( begin(v), end(v), [](int &n){ n--; } );
Osszeg sum = for_each( begin(v), end(v), Osszeg() );
cout << "vektor: ";
for (auto n : v) cout << n << ' ';
cout << endl;
cout << "sszeg: " << sum.osszeg << endl;
}
A program futsnak eredmnye:

vektor: 7 2 30 12 23 29 10 11
sszeg: 124

Az albbi tblzatban sszegyjtttk az j STL algoritmusokat <algorithm>, amelyek jl kiegsztik a


mr meglvket.
bool all_of(InIter kezdet, InIter vg, UnPred
pred)
bool any_of(InIter kezdet, InIter vg, UnPred
pred)

bool none_of(InIter kezdet, InIter vg, UnPred


pred)

true rtkkel tr vissza, ha a pred a [kezdet, vg)


tartomny minden elemre true rtket ad, vagy
ha a lista res.
true rtkkel tr vissza, ha a pred a tartomny
legalbb egy elemre true rtket ad. Ha a lista
res, false rtket ad.
true rtkkel tr vissza, ha a pred a tartomny
minden elemre false rtket ad, vagy ha a lista
res

59

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


InIter find_if_not(InIter kezdet, InIter vg,
UnPred pred)
bool is_permutation(FwIter kezdet1, FwIter vg1,
FwIter kezdet2)
bool is_permutation(FwIter kezdet1, FwIter vg1,
FwIter kezdet2, BinPred pred)

OutIter copy_if(InIter kezdet, InIter vg,


OutIter eredmny, Pred pred)

OutIter copy_n(InIter kezdet, Mret n, OutIter


eredmny)
OutIter move(InIter kezdet, InIter vg, OutIter
eredmny)
OutIter move_backward(InIter kezdet, InIter vg,
OutIter eredmny)
void shuffle(RAIter kezdet, RAIter vg,
RandNGen&& g)
bool is_partitioned(InIter kezdet, InIter vg,
UnPred pred)
pair<OutIter1, OutIter2> partition_copy(InIter
kezdet, InIter vg, OutIter1 ered_true, OutIter2
ered_false, UnPred pred)
FwIter partition_point(FwIter kezdet, FwIter
vg, UnPred pred)

bool is_sorted(FwIter kezdet, FwIter vg)


bool is_sorted(FwIter kezdet, FwIter vg,
Compare comp)
FwIter is_sorted_until(FwIter kezdet, FwIter
vg)
FwIter is_sorted_until(FwIter kezdet, FwIter
vg, Compare comp)
bool is_heap(RAIter kezdet, RAIter vg)
bool is_heap(RAIter kezdet, RAIter vg, Compare
comp)
RAIter is_heap_until(RAIter kezdet, RAIter vg)
RAIter is_heap_until(RAIter kezdet, RAIter vg,
Compare comp)

T min(initializer_list<T> t)
T min(initializer_list<T> t, Compare comp)
T max(initializer_list<T> t)
T max(initializer_list<T> t, Compare comp)

60

Visszaad egy itertort a tartomny azon elemre,


amelyre a pred false rtkkel tr vissza. Ha nincs
ilyen elem, a visszatrsi rtk a vg hivatkozs.
true rtkkel tr vissza, ha a [kezdet1, vg1)
tartomny elemei meggyeznek a kezdet2 pozcin kezddkkel, a sorrendtl fggetlenl. Az
elemek egyezsnek vizsglatra sajt, ktparamteres pred fggvnyt is hasznlhatunk.
A megadott tartomny azon elemeit msolja az
eredmny kezdet terletre, amelyekre a pred
true rtkkel tr vissza. A visszaadott itertor a
clterlet utols adata utni pozcira hivatkozik.
A megadott tartomny els n elemt msolja az
eredmny kezdet terletre.
A megadott tartomny elemeit thelyezi az
eredmny kezdet terletre. Az eredeti tartomny elemeinek rtke definilatlan lesz.
A megadott tartomny elemeit thelyezi az
eredmny kezdet terletre. Egymst tfed
tartomnyok esetn ezt kell hasznlni!
trendezi a tartomny elemeit a megadott g
vletlen szm genertor felhasznlsval.
true rtkkel tr vissza, ha a tartomny azon
elemei, amelyre a prediktum true rtket ad,
megelzik azokat, amelyekre false-t ad.
A megadott tartomny elemeit sztmsolja a
prediktum rtke alapjn. A visszaadott pr
elemei az j tartomnyok vgre hivatkoznak.
A particionlt tartomny els olyan elemre ad
vissza hivatkozst, amelyre a prediktum rtke
hamis.
true rtkkel tr vissza, ha a [kezdet, vg) tartomny elemei nvekv sorrendben rendezettek.
Els esetben az operator<, mg a msodikban a
comp fggvnyt hasznlja az algoritmus.
A tartomny els olyan elemnek itertorval tr
vissza, amely nem kveti a nvekv sorrendet.
true rtkkel tr vissza, ha a tartomny elemei
halmot alkotnak (a make_heap() hvs rendezte
el ket).
A tartomny els olyan elemnek itertorval tr
vissza, amely nem kveti a halom elrendezst.

A listban megadott elemek kzl a legkisebbet


adja vissza.
A listban megadott elemek kzl a legnagyobbat adja vissza.

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


pair<const T&, const T&> minmax(const T& a,
const T& b)
pair<const T&, const T&> minmax(const T& a,
const T& b, Compare comp)
pair<const T&, const T&>
minmax(initializer_list<T> t)
pair<const T&, const T&>
minmax(initializer_list<T> t, Compare comp)
pair<FwIter, FwIter> minmax_element(FwIter kezdet, FwIter vg)
pair<FwIter, FwIter> minmax_element(FwIter kezdet, FwIter vg, Compare comp)

Prban adja vissza a megadott elemek kzl


legkisebbet (first) s a legnagyobbat (second).

void iota(FwIter kezdet, FwIter vg, T rtk)

Az adott tartomny feltlti a megadott rtket


egyesvel nvelgetve. (<numeric>)

Prban adja vissza a megadott tartomny elemei


kzl a legkisebbre (first) s a legnagyobbra
(second) hivatkoz itertorokat.

A tblzatban hasznlt rvidtsek:


BinPred
Compare
FwIter
InIter
OutIter
RAIter
T
UnPred

Ktparamteres prediktum fggvny, amely true rtkkel


jelzi, ha az argumentumaik megfelelnek a feltteleknek.
Ktparamteres sszehasonlt fggvny, amely true rtkkel jelzi, ha az els argumentum kisebb a msodiknl.
ForwardIterator
InputIterator
OutputIterator
RandomAccessIterator
Valamilyen tpus
Egyparamteres prediktum fggvny, amely true rtkkel
jelzi, ha az argumentuma megfelel a feltteleknek.

Az algoritmusok hasznlatt az albbi plda szemllteti:


#include <iostream>
#include <algorithm>
#include <array>
#include <random>
#include <chrono>
using namespace std;
using namespace chrono;
int Fibo() {
static int a0=0, a1=1;
int a2=a0+a1;
a0=a1; a1=a2;
return a2;
}
auto hasonlit = [](int a, int b) { return a>b;};
int main () {
array<int,7> a;
generate_n(begin(a), 7, Fibo);
reverse(begin(a), end(a));
for (int& x: a) cout << x <<' '; cout << endl;
bool rendezett = is_sorted(begin(a), end(a), hasonlit);
if (rendezett)
cout << "rendezett" << endl;
unsigned kezdo = system_clock::now().time_since_epoch().count();
shuffle (begin(a), end(a), default_random_engine(kezdo));
cout << "Kevert: ";

61

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


for (int& x: a) cout << x << ' '; cout << endl;
auto mm = minmax_element(begin(a), end(a));
cout << "min: " << *mm.first << " max: " << *mm.second << endl;
}
A program futsnak eredmnye:

21 13 8 5 3 2 1
rendezett
Kevert: 13 5 2 3 1 21 8
min: 1 max: 21

4.10 Rekordok j megkzeltsben (tuple)


A rekord (tuple) olyan statikus trol, amely tbb, tetszleges tpus rtk trolsra kpes. Hasonl
megfontolsok mellett alkalmazhatjuk, mint a kt adat trolst vgz prt (pair<>, <utility>).
A rekord lerst s hasznlatt segt sablonokat a <tuple> fejllomny tartalmazza:
tuple<>

A rekordot definil osztlysablon.

tuple_size<>

Az osztlysablon constexpr size_t tpus value tagja megadja a rekord elemeinek szmt.

tuple_element<>

A rekord i. elemnek lekrdezst segt osztlysablon, melynek type tagjval


megfelel tpus vltozt hozhatunk ltre.

make_tuple()

Fggvnysablon, amely rekordot llt el az argumentumban szerepl rtkekbl.

forward_as_tupe()

Jobbrtk referencikbl kszt rekordot a fggvnysablon, az argumentumban megadott rtkekbl.

tie()

A fggvnysablon egy rekordot kszt, amely balrtk referencikat tartalmaz


az argumentumaihoz.

tuple_cat()

A megadott rekordok elemeit egyetlen rekordban egyest fggvnysablon.

get()

A fggvnysablon egy referencit ad vissza a rekord i. elemhez, amelyek az


rtkads minkt oldaln felhasznlhatunk.

ignore

Objektum, amely figyelmen kvl hagy minden r irnyul rtkadst. (A tie()


hvsban hasznljuk, a nem kvnt rekordelemek kihagysra.)

Az rekordokkal kapcsolatos sablonok alkalmazst az albbi pldaprogramban foglaltuk ssze. A


megjegyzsek segtenek a kd megrtsben:
#include <iostream>
#include <string>
#include <utility>
#include <tuple>
using namespace std;
void Kiiras(tuple<int&&, double&&, string&&> r) {
cout << get<0>(r) << ", " << get<1>(r) << ", ";
cout << get<2>(r) << endl;
}
int main () {
// rekord konstrulsa, az elemek szmnak lekrdezse s
// az elemek egyenknti kiolvassa:
tuple<int,double,string> r1(2004, 10.2, "Ivn");
int elemszam = tuple_size<decltype(r1)>::value;
tuple_element<0,decltype(r1)>::type elem0 = get<0>(r1);
tuple_element<1,decltype(r1)>::type elem1 = get<1>(r1);

62

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse


tuple_element<2,decltype(r1)>::type elem2 = get<2>(r1);
cout
cout
cout
cout

<<
<<
<<
<<

"elemek szma:
"1. elem: " <<
"2. elem: " <<
"3. elem: " <<

" << elemszam << endl;


elem0 << endl;
elem1 << endl;
elem2 << endl;

// rekord ltrehozsa adatokbl, s kiolvassa


int a;
double b;
string s;
auto r2 = make_tuple(2004, 10.2, "Ivn");
auto r3 = make_tuple<int, double, string>(2004, 10.2, "Ivn");
tie(a, b, s) = r2;
cout << "a: " << a << endl;
cout << "b: " << b << endl;
cout << "s: " << s << endl;
// rekordok sszekapcsolsa, s rszleges kiolvassa:
pair<string, int> sn = {"MXY", 238};
auto r4 = tuple_cat(r2, tuple<string, int>(sn));
string ss;
int nn;
tie(ignore, ignore, ignore, ss, nn) = r4;
cout << ss << nn << endl;
// rekord mdostsa, s tovbbtsa fggvnynek
// jobbrtk rerencival
Kiiras(forward_as_tuple(1998, 14882.0, string("C++")));
tuple<int&&, double&&, string&&> r5(1998, 14882.0, string("C++"));
get<0>(r5) = 2011;
get<1>(r5) = 14882.0;
get<2>(r5) = string("C++11");
Kiiras(r5);
}
A program futsnak eredmnye:

elemek szma: 3
1. elem: 2004
2. elem: 10.2
3. elem: Ivn
a: 2004
b: 10.2
s: Ivn
MXY238
1998, 14882, C++
2011, 14882, C++11

4.11 A szabvnyos C++ nyelv deklarcis llomnyai


A tblzatban kk sznnel jelltk az jonnan bevezetett, mg bord sznnel a mdostott fejllomnyokat.
A C++ nyelvet tmogat knyvtr
Tpusok (NULL, size_t stb.)
Rgztett mret tpusok s formtum makrk
Az implementci jellemzi
Programindts s -befejezs
Dinamikus memriakezels
Tpusazonosts
Egyb futsidej tmogats

<cstddef>
<cstdint>, <cinttypes>
<limits>, <climits>, <cfloat>
<cstdlib>
<new>
<typeinfo>, <typeindex>, <type_traits>
<cstdarg>, <csetjmp>, <ctime>, <csignal>,
<cstdlib>,<cstdbool>, <cstdalign>, <initializer_list>

63

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse

Hibakezelsi knyvtr
Kivtelkezels
Kivtelosztlyok
Assert makrk
Hibakdok
Rendszerhiba-tmogats

<exception>
<stdexcept>
<cassert>
<cerrno>
<system_error>

ltalnos szolgltatsok knyvtra


Mveleti elemek (STL)
Mveletobjektumok (STL)
Memriakezels (STL)
Specilis osztlysablonok (STL)
Dtum- s idkezels

<utility>
<functional>
<memory>, <scoped_allocator>
<bitset>, <tuple>
<ctime>, <chrono>

Sztring knyvtr
Sztring osztlyok
Nullavg karakterlncok kezelst segt
fggvnyek

<string>
<cctype>, <cwctype>, <cstring>, <cwchar>, <cuchar>

Orszgfgg (helyi) belltsok knyvtra


A helyi sajtossgok szabvnyos kezelse
A C knyvtr helyi belltsai
Unicode konverzik tmogatsa

<locale>
<clocale>
<codecvt>

A trolk knyvtra (STL)


Szekvencilis trolk (STL)
Asszociatv trolk (STL)
Nem rendezett asszociatv trolk (STL)
Trol adaptcik (STL)

<array>, <deque>, <list>, <vector>, <forward_list>


<map>, <set>
<unordered _map>, <unordered_set>
<queue>, <stack>

Iterrotok (ltalnostott mutatk) knyvtra (STL)


Itertorelemek, elre definilt itertorok, adat- <iterator>
folyam itertorok (STL)

Algoritmusok knyvtra
Adatsorkezels, rendezs, keress stb. (STL)
A C knyvtr algoritmusai

<algorithm>
<cstdlib>

Numerikus knyvtr
Komplex szmok
Szmtmbk
ltalnostott numerikus mveletek (STL)
A C knyvtr numerikus elemei
Fordtsidej racionlis aritmetika
Vletlen szm ellltsa
A lebegpontos krnyezet kezelse

<complex>
<valarray>
<numeric>
<cmath>, <cstdlib>
<ratio>
<random>
<cfenv>

Input/output knyvtr
Forward (elrevetett) deklarcik
Szabvnyos iostream objektumok
Az iostream osztlyok alaposztlya
Adatfolyam pufferek
Adatformzs s manipultorok
Sztring adatfolyamok
Fjl adatfolyamok

64

<iosfwd>
<iostream>
<ios>
<streambuf>
<istream>, <ostream>, <iomanip>
<sstream>
<fstream>, <cstdio>

Tth Bertalan: A C++11 nyelv j lehetsgeinek ttekintse

Regulris kifejezsek knyvtr


Regulris kifejezsek kezelse

<regex>

Mveletek a konkurens programozshoz


Atomi tpusok s -mveletek

<atomic>

Thread (programszl) knyvtr


Szlak ltrehozsa s vezrlse

<thread>, <mutex>, <condition_variable>, <future>

65

Das könnte Ihnen auch gefallen