C++11

Z Wikipedie, otevřené encyklopedie
Autor jazyka C++ Bjarne Stroustrup (vlevo) na konferenci CEE-SECR 2010 v Moskvě

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[editovat | editovat zdroj]

Reference jako r-hodnota a move konstruktor[editovat | editovat zdroj]

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[editovat | editovat zdroj]

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[editovat | editovat zdroj]

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[editovat | editovat zdroj]

Externí šablona[editovat | editovat zdroj]

extern template class std::vector<MyClass>;

Rozšíření jádra pro lepší použití jazyka[editovat | editovat zdroj]

Initializer lists[editovat | editovat zdroj]

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[editovat | editovat zdroj]

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[editovat | editovat zdroj]

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[editovat | editovat zdroj]

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[editovat | editovat zdroj]

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ů[editovat | editovat zdroj]

//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[editovat | editovat zdroj]

Nové knihovny:

Reference[editovat | editovat zdroj]

  1. ISO/IEC 14882:2011 [online]. [cit. 2011-09-03]. Dostupné online. 
  2. cppreference.com. en.cppreference.com [online]. [cit. 2021-09-15]. Dostupné online. 
  3. Recent milestones: C++17 published, C++20 underway. isocpp.org [online]. [cit. 2018-07-20]. Dostupné online. (anglicky)