C++11
C++11 (dříve C++0x) je standard programovacího jazyka C++. Byl schválen organizací ISO dne 12. srpna 2011 a nahrazuje C++03. Označení navazuje na tradici pojmenovávání verzí jazyka podle roku publikování specifikace. C++11 přidává několik prvků k jádru jazyka a rozšiřuje standardní C++ knihovnu. V září 2011 byl standard publikován jako ISO/IEC 14882:2011.[1]
Nejnovějšími standardy jsou postupně C++14, C++17 a C++20, a pracuje se na standardu C++23.[2][3]
Při vytváření standardu C++11 byl kladen důraz na:
- Udržení kompatibility s C++98 a případně s jazykem C.
- Rozšiřovat standardní knihovnu, jádro rozšiřovat minimálně.
- Zjednodušovat použití jazyka a nezavádět jednoúčelové techniky.
- Zvýšení výkonu a umožnit více pracovat přímo s hardwarem.
Rozšíření jádra pro rychlejší běh
Reference jako r-hodnota a move konstruktor
Umožňuje použít referenci na objekt jako r-hodnotu. R-hodnota je dočasná konstanta, do které nelze nijak zapisovat.
int a;
a = 5 + 10 // (5 + 10) je r-hodnota
(5 + 10) = a; // nelze přiřadit hodnotu r-hodnotě.
int& b = 10; // nelze, nemůže existovat nekonstantní reference na r-hodnotu, konstanta není uložená v paměti, ale dosazena překladačem
const int& b = 10; // lze, za b se vždy dosadí 10
int&& b = 10; // lze, uloží se do paměti jako dočasná proměnná, inicializuje se na hodnotu 10
Move konstruktor lze využít pro přesun zdrojů z jedné třídy do druhé bez alokace a dealokace paměti. C++11 zavádí operátor && jako referenci na r-hodnotu. Move konstruktor je definován jako Trida(Trida&& trida)
, a zavolá se při konstrukci objektu z reference na objekt, který je r-hodnotou.
class Array {
int* pole;
size_t s;
public:
// Konstruktor
Array(size_t s) : s(s) {
pole = new int[s];
}
// Kopírovací konstruktor
Array(const Tr1& par) {
pole = new int[s];
memcpy(pole, par.pole, sizeof(int) * s);
}
// Move konstruktor
Array(Tr1&& par) {
pole = par.pole;
s = par.s;
par.pole = 0;
par.s = 0;
}
~Array() {
delete[] pole;
}
};
Array pole1(100); // Zavolá standardní konstruktor
Array pole2(static_cast<Array&&>(pole1)); // Přetypuje pole1 na referenci na r-hodnotu, a zavolá move konstruktor
// pole2 je stejné jako bylo pole1 a pole1 je prázdné
constexpr – Obecné konstantní výrazy
C++11 zavádí klíčové slovo constexpr
, které u funkce nebo objektu vynutí, že bude vyhodnocena (objekt konstruován) v době kompilace.
int get_five() {
return 5;
}
int some_value[get_five() + 7]; // Nelze použít, get_five() není konstantní výraz
enum {
five = get_five(); // Nelze použít, get_five() není konstantní vyraz
};
constexpr int get_five() {
return 5;
}
int some_value[get_five() + 7];
enum {
five = get_five();
};
Nová definice POD
C++03 má přísná pravidla, pro označení třídy nebo struktury jako plain old data (POD – surová data, přístup z C++ ke struktuře v jazyce C). Taková třída (struktura) vyžaduje kompatibilitu s jazykem C a umožnit statickou inicializaci. Pro takovou třídu v C++03 nelze definovat nevirtuální metody, přestože v tomu nebraní technický problém.
C++11 umožňuje jako POD použít třídu nebo strukturu, která není virtuální, nedědí virtuální třídu ani ji nemá jako členskou proměnnou. Třídy dělí na trivial a standard-layout. Triviální třída musí mít triviální konstruktor a umožňuje statickou inicializaci a použití funkce memcpy
.
Rozšíření jádra pro rychlejší kompilaci
Externí šablona
extern template class std::vector<MyClass>;
Rozšíření jádra pro lepší použití jazyka
Initializer lists
C++11 rozšiřuje statickou inicializaci pole nebo struktury známou z C. Pomocí std::initializer_list<>
umožňuje konstruktoru předat pole inicializačních parametrů uzavřených v {}.
// inicializace v C
int pole[] = {10, 10}; // inicializace pole
typedef struct {
int a;
int b;
} Struktura;
Struktura strukt = {10, 10}; // inicializace struktury
// inicializace v C++11
class Trida {
public:
Trida(int par);
};
Trida pole[] = {10, 10}; // inicializace pole trid
class Trida {
public:
Trida(std::initializer_list<int> list);
};
Trida pole = {1, 2}; // inicializace tridy
Type inference
C++11 zavádí dvě nové metody, jak deklarovat proměnné. Klíčové slovo auto
doplní typ proměnné automaticky podle přiřazované hodnoty. Funkce decltype(výraz)
vrací typ parametru.
auto i = 15; // i bude int;
decltype(i) j; // j bude int;
Výhodu přináší u složitých typů, zkracuje zápis.
// C++03
for(std::vector<int>::const_iterator it = data.cbegin(); it != data.cend(); ++it);
// C++11
for(auto it = data.cbegin(); it != data.cend(); ++it);
For cyklus
Rozšiřuje o novou definici cyklu for. Tento cyklus je známý z jiných jazyků jako cyklus foreach.
int pole[10];
for(int& i : pole) {
}
Tento cyklus lze také použít pro kontejnery, které poskytují metody begin a end.
Lambda funkce
C++11 zavádí anonymní funkce (lambda funkce). Lambda funkce umožňuje deklarovat i definovat dočasnou funkci (například jako parametr funkce nebo uvnitř jiné funkce).
[externí_proměnné](parametry)->návratový_typ { tělo funkce; }
V hranatých závorkách lze předat proměnné z rozsahu platnosti, ve které je funkce definovaná. Lze předat všechny, nebo jen výčet a je možné je předat hodnotou nebo referencí.
[] // funkce nema pristup k externim promennym
[x, &y] // k promenne x lze ve funkci pristupovat jako k hodnote, k y jako k referenci
[&] // vsechny promenne jsou predany referenci
[=] // vsechny promenne jsou predany hodnotou
[&, x] // x je predano hodnotou, vsechny ostatni referenci
Příklad lambda funkce:
[](int x, int y) { return x + y; } // Navratovy typ je implicitni, funkce nevidi zadne promenne mimo rozsah sve platnosti
int a = 10;
[&](int x, int y)->int { return x + y + a; } // Navratovy typ je explicitni, funkce ma pristup ke vsem promennym z rozsahu platnosti
// ve ktere je definovana, promenne jsou predany referenci
[=](int x, int y)->int { return x + y + a; } // Promenne jsou predany hodnotou
Aliasy na jmenné prostory
namespace ab
{
int zdvojnasob(int x)
{
return x*2;
}
}
namespace x=ab;
x::zdvojnasob(5);//To samé jako ab::zdvojnasob(5)
Nová syntaxe typových aliasů
//C++98
typedef int my_type;
//C++11
typedef int my_type;//Zpětná kompatibilita
using my_type=int;//Nová syntaxe
//Toto pomocí typedef nelze:
template<typename T>using ptr=T*;
Rozšíření standardní knihovny
Nové knihovny:
- chrono: práce s časem
- codevct: konverze Unicode kódování
- random: pokročilé generování pseudonáhodných čísel
- ratio: zlomky, vyhodncené v době kompilace
- regex: podpora regulárních výrazů
Reference
- ISO/IEC 14882:2011 [online]. [cit. 2011-09-03]. Dostupné online.
- cppreference.com. en.cppreference.com [online]. [cit. 2021-09-15]. Dostupné online.
- Recent milestones: C++17 published, C++20 underway. isocpp.org [online]. [cit. 2018-07-20]. Dostupné online. (anglicky)