C++0x

Alprogramok, modulok

Lambda kifejezések

A C++ bevezeti a név nélküli függvényeket a következő szintaxissal:

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

Látható, hogy visszatérési érték típusát sehol nem adtuk meg. Ebben az esetben azért, mert egyértelmű. Nem kötelező visszatérési értéket megadni, ha a függvény törzse egyetlen return utasításból áll, ekkor a visszatérési értéket a fordító kikövetkezteti. Ha a függvény nem így épül fel, és nem adjuk meg a visszatérési érték típusát, az void lesz. A következő példában ki kell rakni a visszatérési érték típusát:

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

Az lambda kifejezések fel tudják használni a definíciójuk helyén látható változókat is. Ezeket a [] jelek között sorolhatjuk fel. A paraméter-átadás érték szerinti, hacsak nem jelöljük & jellel:

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

A fenti példa kiírja a tömbben található értékek összegét. A környezetből átvett változókat sem muszáj felsorolni (kivétel a this, amelyet explicit át kell adni), ha megadjuk az alapértelmezett paraméter-átadási módot: [&] a referencia szerinti, [=] az érték szerinti. Ezt felülbírálhatjuk, ha a változót explicit kiírjuk. Pl: [&, value] illetve [=, &ref]. Ekkor a value érték szerint, a ref referencia szerint adódik át.

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

Ha ilyen lambda kifejezést eltárolunk, és nem a definiálás helyén hívjuk meg, a viselkedés definiálatlan.

Alternatív szintaxis

A C++ régi jól ismert problémája a sablon összeadás függvény, amely típusparamétereit a fordító nem tudja kikövetkeztetni (A Ret paraméter nem szerepel az argumentumokban).

template<typename Ret, typename LHS, typename RHS> Ret AddingFunc(const LHS &lhs, const RHS &rhs) { return lhs + rhs; }

A C++ új függvény szintaxist vezet be, amelyben használható a decltype kulcsszó is a visszatérési érték kiszámítására:

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

Az új szintaxist természetesen nem csak sablonokban használhatjuk:

struct SomeStruct { auto FuncName(int x, int y) -> int; }; auto SomeStruct::FuncName(int x, int y) -> int { return x + y; }

Move szemantika

A szabványos C++-ban belső változókkal nem szabad referencia szerint visszatérni, ez nem megjósolható viselkedéshez vezet. Érték szerinti visszatérésnél viszont az objektumot lemásoljuk, ami sok esetben nem hatékony.

Hasonló eset fordulhat elő ideiglenes változóknál. Ha egy kifejezést adunk át egy függvénynek, azt általában const & típussal oldjuk meg, ekkor viszont nem módosíthatjuk az értékét akkor sem, ha tudjuk, hogy az érték a függvény visszatérése után felszabadul.

Ezeket a problémákat egyszerűen meg lehet oldani a move konstruktor bevezetésével. Egy objektum move konstruktora úgy működik, hogy az eredeti objektum adatait átveszi úgy, hogy az eredetiből törli. Például szabványos könyvtár vector típusa úgy működik, hogy belül az adatokat tömbben tárolja. A move konstruktor egyszerűen ezt a mutatót átmásolja magának, és a helyére üres tömböt rak. Ha ezzel a konstruktorral tudnánk átadni értéket, nem lenne szükség a másolásra.

A probléma az, hogy hogyan különböztessük meg az érték szerinti, a referencia szerinti, és a move szemantikájú paraméter-átadásokat Ennek a megoldására a C++ bevezeti a jobbérték-referencia típusokat, amelyet typename && típussal jelölünk. Jobbérték-referencia típusú argumentumként csak olyan kifejezést lehet átadni, amely nem balérték. Balértéket csak úgy tudunk átadni, ha az std::move() függvénnyel beburkoljuk.

bool is_r_value(int &&) { return true; } bool is_r_value(const int &) { return false; } int main() { int i; is_r_value(i); // false is_r_value(i+3); // true is_r_value(std::move(i)); // true }

Visszatérés jobbérték-referenciával:

std::vector<int> &amp;&amp; function() { std::vector<int> ret; // ret feltöltése jó sok adattal return ret; }