Reference v C++ jsou vždy konstantní

Od Petr Zemek, 2016-06-20

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

Obsah tohoto pole je soukromý a nebude veřejně zobrazen.

Filtrované HTML (využíváno)

  • Povolené HTML značky: <a href hreflang> <em> <strong> <cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <table>
  • Zvýraznění syntaxe kódu lze povolit přes následující značky: <code>, <blockcode>, <bash>, <c>, <cpp>, <haskell>, <html>, <java>, <javascript>, <latex>, <perl>, <php>, <python>, <ruby>, <rust>, <sql>, <text>, <vim>, <xml>, <yaml>.
  • Řádky a odstavce se zalomí automaticky.
  • Webové a e-mailové adresy jsou automaticky převedeny na odkazy.
CAPTCHA
3 + 5 =
Vyřešte tento jednoduchý matematický příklad a vložte výsledek. Např. pro 1+3 vložte 4.
Nějak se mi tady rozmohl spam, takže poprosím o ověření.