Hvad er forskellene mellem en pointervariabel og en referencevariabel i C++?

Jeg ved godt, at referencer er syntaktisk sukker, så kode bliver lettere at læse og skrive.

Men hvad er forskellene?


Resumé af svarene og links nedenfor:

  1. En pointer kan gentildeles et vilkårligt antal gange, mens en reference ikke kan gentildeles efter binding.
  2. Pointer kan pege på intet sted (NULL), mens en reference altid henviser til et objekt.
  3. Du kan ikke tage adressen på en reference, som du kan med pointers.
  4. Der'er ingen "referencearitmetik" (men du kan tage adressen på et objekt, der peges på af en reference, og lave pointeraritmetik på den som i &obj + 5).

For at afklare en misforståelse:

C++-standarden er meget omhyggelig med at undgå at diktere, hvordan en compiler må implementere referencer, men alle C++ compilere implementerer referencer som pointere. Det vil sige, at en deklaration som:

int &ri = i;

hvis den ikke er optimeret helt væk, allokerer den samme mængde lagerplads som en pointer, og placerer adressen af i i` i dette lager.

Så en pointer og en reference bruger begge den samme mængde hukommelse.

Som en generel regel gælder følgende,

  • Brug referencer i funktionsparametre og returtyper for at give nyttige og selvdokumenterende grænseflader.
  • Brug pointere til at implementere algoritmer og datastrukturer.

Interessant læsning:

  1. En pointer kan tildeles igen:

    int x = 5;
    int y = 6;
    int *p;
    p = &x;
    p = &y;
    *p = 10;
    assert(x == 5);
    assert(y == 10);

    En reference kan ikke, og skal tildeles ved initialiseringen:

    int x = 5;
    int y = 6;
    int &r = x;
  2. En pointer har sin egen hukommelsesadresse og størrelse på stakken (4 bytes på x86), mens en reference deler den samme hukommelsesadresse (med den oprindelige variabel), men også optager noget plads på stakken. Da en reference har samme adresse som den oprindelige variabel selv, kan man roligt betragte en reference som et andet navn for den samme variabel. Bemærk: Det, som en pointer peger på, kan være på stakken eller på heap'en. Det samme gælder for en reference. Min påstand i denne udtalelse er ikke, at en pointer skal pege på stakken. En pointer er blot en variabel, der indeholder en hukommelsesadresse. Denne variabel befinder sig på stakken. Da en reference har sin egen plads på stakken, og da adressen er den samme som den variabel, den henviser til. Mere om [stack vs. heap][1]. Dette indebærer, at der er en reel adresse for en reference, som compileren ikke fortæller dig.

    int x = 0;
    int &r = x;
    int *p = &x;
    int *p2 = &r;
    assert(p == p2);
  3. Du kan have pointere på pointere på pointere på pointere, der giver ekstra indirekte niveauer. Hvorimod referencer kun giver et enkelt niveau af indirekte led.

    int x = 0;
    int y = 0;
    int *p = &x;
    int *q = &y;
    int **pp = &p;
    pp = &q;//*pp = q
    **pp = 4;
    assert(y == 4);
    assert(x == 0);
  4. Pointer kan tildeles nullptr direkte, mens reference ikke kan tildeles direkte. Hvis du prøver hårdt nok, og du ved hvordan, kan du gøre adressen på en reference til nullptr. På samme måde kan man, hvis man prøver hårdt nok, få en reference til en pointer, og så kan denne reference indeholde nullptr.

    int *p = nullptr;
    int &r = nullptr; 
Kommentarer (43)

Bortset fra syntaktisk sukker er en reference en const pointer (ikke pointer til en const). Du skal fastsætte, hvad den refererer til, når du deklarerer referencevariablen, og du kan ikke ændre det senere.

Opdatering: Nu hvor jeg tænker lidt mere over det, er der en vigtig forskel.

En const pointer's mål kan erstattes ved at tage dens adresse og bruge en const cast.

En reference's mål kan ikke erstattes på nogen måde med undtagelse af UB.

Dette skulle gøre det muligt for compileren at foretage mere optimering af en reference.

Kommentarer (5)

En reference kan aldrig være NULL.

Kommentarer (10)