A 1.9.3-as részben, a hagyományos C nyelv ismertetésénél említettük, hogy a függvények érték szerint veszik át az aktuális paramétereiket. (A tömböket ebbõl a szempontból tekintsük olyan pointereknek, amelyek adott számú értékes adat számára lefoglalt tárterületre mutatnak - lásd a 1.9.6-os szakaszt. Igy a tömbök is beleférnek az "érték szerint" fogalmába, hiszen a mutatókat tényleg érték szerint adjuk át.) Ha egy változót cím szerint akartunk paraméterként átadni, akkor a formális paraméterlistában az adott típusra mutató pointert kellett deklarálnunk, a függvénytörzsben az indirekció operátorát kellett alkalmaznunk, és a függvény meghívásakor az aktuális paraméterlistában magunknak kellett explicit módon gondoskodnunk arról, hogy a megfelelõ paraméterhelyre a megfelelõ változó címe kerüljön. Ennek a dolognak az a nagy hátránya, hogy a függvénytörzsben nem különülnek el szintaktikailag az igazi tömbök és a cím szerint átadott skalárjellegû változók.
A C++-ban ilyen, és hasonló jellegû problémák áthidalására bevezették az ún. cím szerint nyilvántartott, vagy referencia típus (reference type) fogalmát és ehhez definiálták a & típusmódosító operátort. Igy például a
int& r;deklaráció azt jelenti, hogy r olyan változó, amely egy egész típusú változóra vonatkozó referenciát tartalmazhat. Úgy is felfoghatjuk a dolgot, hogy egy ilyen fajta változó egy olyan konstans pointer-kifejezés, amelyre vonatkozólag automatikusan végrehajtódik egy indirekció-mûvelet, amikor az adott referencia típusú változóra hivatkozunk. Ez három dolgot von maga után. Az egyik, hogy a fenti példa szerinti r változó minden olyan helyen állhat, ahol egy int típusú változó is állhat, azaz egész típusú kifejezésekben akár balérték, akár jobbérték lehet. A második, hogy a referencia típusú változókkal semmilyen mûvelet nem végezhetõ, hiszen minden hivatkozás alkalmával minden egyebet megelõz az implicit indirekció mûvelet (dereference operation, lásd a 1.5.2 alatt az egyoperandusú * operátorról leírtakat). Ezzel áll szoros összefüggésben a harmadik fontos dolog, hogy nincs értelme egy cím szerint nyilvántartott típusú változót inicializálás nélkül definiálni. Tehát csak az alábbihoz hasonló definíciónak van értelme:
int ii = 0; int& rr = ii;Ekkor az rr++; utasítás szintaktikailag ugyan helyes, de nem az rr változó inkrementálódik, hanem az az int típusú tárterületfoglaló tárolási egység, amelyiknek a címét rr tartalmazza. Ez a fenti példában éppenséggel az ii változó. Ez az értelmezés triviális akkor, amikor az inicializáló kifejezés egy balérték, de nem kötelezõ, hogy az inicializátor balérték legyen, sõt, az sem kötelezõ, hogy a referncia típus alaptípusába tartozzon. Ilyen esetekben
double& dr = 1;Ez a fentiek alapján a következõképpen értelmezhetõ:
double* drp; double temp; temp = (double)1; drp = &temp;A használat során a (*drp) kifejezés egyenértékû a dr-rel.
A referencia típus igazán kellemes felhasználási területe a bevezetõben is említett függvényparaméter-deklaráció. Ez azt jelenti, hogy a formális paraméterlistában már lehetõségünk van arra, hogy egy paramétert ne a reá mutató pointer segítségével adjunk át cím szerint, hanem jelezzük, hogy egy olyan változóról van szó, amit cím szerint kell átadnuk (mert például kimenõ paraméterként is szükségünk lesz rá), ugyanakkor a függvénytörzsben a többi, érték szerint átadott változóhoz hasonló módon - ugyanolyan szintaktikával - szeretnénk kezelni. A 1.9.3-as részben közölt egyszerû példa a referncia típus felhasználásával így néz ki:
void f1(long& a) { a += 2L; }Ekkor az
alfa = 0L; f1(alfa);kódrészlet szintaktikailag helyes, és hatására alfa értéke 2L lesz. A különbözõ paraméterátadási lehetõségeket szemlélteti a következõ kis program:
#include <stdio.h> // ********************************************************** int any_function(int par_by_value, //Ertek szerinti int int* use_for_arrays,//Ertek szerinti pointer int& par_by_address)//Cim szerinti int // ********************************************************** { int work; work = par_by_value; par_by_value *= 3; *use_for_arrays = par_by_address * work; par_by_address = work * work; return par_by_value; } // ********************************************************** main() // ********************************************************** { int x = 2, y[ ] = { 1, 2 }, z = 10, w = 0; w = any_function(z,y,x); printf("%d %d %d %d\n",x,y[0],z,w); }Az any_function függvény harmadik paraméterét deklaráltuk referencia típusúnak, erre a típusnév (int) után álló & típusmódosító operátor utal. Tekintsük át a fenti program mûködését.
A main-ben any_function meghívása elõtt az x, y[0], z és w változók értéke rendre 2, 1, 10 és 0, a w-nek függvényhívással történõ értékadás eredményeképpen (mellékhatásként) pedig x, y[0], z, valamint w a 100, 20, 10 és 30 értékeket veszik fel; a szabványos kimeneten ezek a számok fognak sorra megjelenni. Látható, hogy az érték szerint átadott paraméter (z) nem változott meg, y[0] új értéket kapott, hiszen a reá mutató pointeren keresztül indirekt módon címezve beleírtunk, és a cím szerint átadott skalár, x is új értékkel bír a függvényhívás után. Látható az is, hogy par_by_value és par_by_address használata szintaktikailag azonos.
Az any_function deklarációjakor a par_by_address parméternél használt megoldás hasonlít ahhoz, amit a Pascal nyelv alkalmaz. Pascal-ban is alapértelmezés szerint érték szerint adódnak át a paraméterek; ott a VAR kulcsszóval jelezhetjük a cím szerinti paraméterátadást, ugyanakkor a FUNCTION, vagy PROCEDURE törzsében az érték, vagy cím szerint átadott paraméterek használatában nincs szintaktikai különbség.
A referencia típust függvények visszatérési típusaként is nagyon jól fel lehet használni. Gondoljunk csak a 1.12-es pontban a balértékek kapcsán deklarált char *get_buff_pos(int i) függvényre. Ennek a függvénynek balértékként való alkalmazása így nézett ki:
*get_buff_pos(1) = 'b';Ha függvényünket char & típusú visszatérési értékkel deklaráljuk, akkor a referencia típus tulajdonságai következtében a get_buff_pos(1) kifejezés minden további nélkül érvényes balérték kifejezés lesz, tehát a fenti értékadó utasítást így írhatjuk:
get_buff_pos(1) = 'b';Vegyük észre, hogy a referencia típusú visszatérési érték miatt a char& get_buff_pos(int i) függvény egy értékadó utasítás mindkét oldalán állhat. A referencia típusról itt elmondottak elsõsorban a fogalom megértetését szolgálják. A referencia típus leges-legfontosabb szerepet azonban a felhasználó által definiált típusokra vonatkozó operátor-függvényeknek definiálásánál játssza - ezek visszatérési értéke ugyanis az adott típusra vonatkozó referencia-típusú.
Vegyük észre, hogy a referencia típust képzõ & operátor természetes kiegészítése a hagyományos C típusmódosító operátorainak: míg a * indirekció operátornak, a [ ] indexelõ operátornak és a ( ) függvényaktivizáló operátornak volt párja a típusmódosító operátorok között, addig az 'address of' operátornak (egyoperandusú &) nem volt.