Aneb proč nedává smysl říkat "x
je konstantní reference" a že tím programátor ve skutečnosti myslí "x
je reference na konstantu".
Konstantní ukazatele vs ukazatele na konstanty
Začněme ukazateli, abychom si lépe ilustrovali rozdíl mezi konstantním ukazatelem a ukazatelem na konstantu. Konstantní ukazatel je ukazatel, jehož hodnotu (adresu kam ukazuje) nelze po vytvoření změnit:
int a = 1, b = 2; int* const p = &a; // Inicializace. p = &b; // Chyba! p je konstantní proměnná.
Funguje to stejně, jako kdybychom pracovali s jakýmkoliv jiným typem:
int const c = 1; // Inicializace. c = 2; // Chyba! c je konstantní proměnná.
Pokud vás onen zápis definice proměnné c
výše překvapil, tak vězte, že se jedná o zápis ekvivalentní tomuto:
const int c = 1; // Jiný zápis toho stejného.
Již tedy víme, že nelze změnit p
, aby ukazoval na něco jiného. Můžeme však ale změnit hodnotu proměnné, na kterou ukazuje:
*p = 2; std:: cout << a << '\n'; // Vypíše 2.
Opačným případem je ukazatel na konstantu. U něj lze změnit jeho hodnotu (adresu, kam ukazuje), ale již nelze změnit hodnotu odkazované proměnné:
const int* q = &a; // Inicializace. q = p; // OK, ukazatel q nyní ukazuje tam, kde p. *q = 3; // Chyba! q je ukazatel na konstantu.
Oba výše uvedené typy ukazatelů lze zkombinovat a dostat tak konstantní ukazatel na konstantu:
const int* const r = &a; r = &b; // Chyba! r je konstantní ukazatel. *r = 4; // Chyba! r je ukazatel na konstantu.
Vše jasné? Fajn, můžeme jít dál :).
Jak je to s referencemi?
Když už víme, jak to funguje u ukazatelů, tak se můžeme podívat na reference. V C++ je každá reference implicitně konstantní, protože po vytvoření reference ji nelze změnit, aby odkazovala na něco jiného:
int d = 1, e = 2; int &u = d; // Inicializace, u odkazuje na d. u = e; // Zkopíruje obsah e do u (nedojde ke změně toho, na co proměnná odkazuje). e = 3; std::cout << u << '\n'; // Vypíše 2.
Překladač nám dokonce ani nepovolí následující zápis, který by měl znamenat konstantní reference:
int& const v = d; // Chyba! const nelze aplikovat tímto způsobem.
Nyní však můžete namítnout následující: "Už jsem několikrát slyšel termín 'konstantní reference'." Ano, to jsem slyšel i já. Co tím však programátor myslel, byla ve skutečnosti reference na konstantu:
const int& v = d; // Inicializace. v = e; // Chyba! v ukazuje na konstantu.
Ekvivalentním zápisem je pak toto:
int const& v = d; // Jiný zápis toho stejného
Oba dva zápisy se v praxi používají. Někomu se líbí ten první, někomu ten druhý.
Závěr
Abych to shrnul, tak:
- Pokud uslyšíte termín "konstantní reference", změňte si jej v hlavě na "reference na konstantu".
- Pokud používáte termín "konstantní reference", přestaňte jej používat a místo toho používejte přesnější "reference na konstantu".
Nikdo však není dokonalý a tak se nám všem čas od času stane, že nevědomky použijeme termín "konstantní reference". Naštěstí však věřím, že nám i tak bude porozuměno :).