Jste zde

Reference v C++ jsou vždy konstantní

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 :).

Přidat komentář