Pass by pointer & Pass by reference [duplicate]

Możliwy duplikat:
jakie są różnice między zmienną wskaźnika a zmienną odniesienia w C++?
czy są korzyści z przechodzenia przez wskaźnik nad przechodzeniem przez odniesienie w C++?

W obu przypadkach osiągnąłem wynik. Więc kiedy jeden jest preferowany nad drugim? Jakie są powody, dla których używamy jednego nad drugim?

#include <iostream>
using namespace std;
void swap(int* x, int* y)
{
    int z = *x;
    *x=*y;
    *y=z;
}
void swap(int& x, int& y)
{
    int z = x;
    x=y;
    y=z;
}

int main()
{
    int a = 45;
    int b = 35;
    cout<<"Before Swap\n";
    cout<<"a="<<a<<" b="<<b<<"\n";

    swap(&a,&b);
    cout<<"After Swap with pass by pointer\n";
    cout<<"a="<<a<<" b="<<b<<"\n";

    swap(a,b);
    cout<<"After Swap with pass by reference\n";
    cout<<"a="<<a<<" b="<<b<<"\n";
}

Wyjście

Before Swap
a=45 b=35
After Swap with pass by pointer
a=35 b=45

After Swap with pass by reference
a=45 b=35
Author: Community, 2011-12-20

5 answers

Odniesienie jest semantycznie następujące:

T& <=> *(T * const)

const T& <=> *(T const * const)

T&& <=> [no C equivalent] (C++11)

Podobnie jak w przypadku innych odpowiedzi, następująca z C++ FAQ jest jednolinijkową odpowiedzią: referencje, gdy jest to możliwe, wskaźniki, gdy są potrzebne.

Przewaga nad wskaźnikami polega na tym, że potrzebujesz wyraźnego rzutu, aby przekazać NULL. Ale to wciąż możliwe. Z testowanych przeze mnie kompilatorów, żaden nie wyświetla ostrzeżenia dla:

int* p() {
    return 0;
}
void x(int& y) {
  y = 1;
}
int main() {
   x(*p());
}
 26
Author: moshbear,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-19 05:04:48

W rzeczywistości większość kompilatorów emituje ten sam kod dla obu wywołań funkcji, ponieważ odwołania są zazwyczaj implementowane za pomocą wskaźników.

Zgodnie z tą logiką, gdy argument (non-const) reference type jest używany w ciele funkcji, wygenerowany kod po prostu po cichu operuje na adresie argumentu i dereferuje go. Ponadto, gdy zostanie napotkane wywołanie takiej funkcji, kompilator wygeneruje kod, który przekazuje adres argumentów zamiast kopiowanie ich wartości.

Zasadniczo odniesienia i wskaźniki nie różnią się zbytnio z punktu widzenia implementacji, główna (i bardzo ważna) różnica tkwi w filozofii: odniesienie to sam obiekt, tylko o innej nazwie.

Odniesienia mają jeszcze kilka zalet w porównaniu ze wskaźnikami (np. nie mogą być NULL, więc są bezpieczniejsze w użyciu). W związku z tym, jeśli można używać C++, to przechodzenie przez odniesienie jest ogólnie uważane za bardziej eleganckie i powinno być preferowane. Jednakże, w C, nie ma przejścia przez odniesienie, Więc jeśli chcesz napisać kod w C (lub, horribile dictu, kod, który kompiluje się zarówno z kompilatora C i C++, choć to nie jest dobry pomysł), będziesz musiał ograniczyć się do używania wskaźników.

 6
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-09 19:55:50

Pass by pointer jest jedynym sposobem, w jaki możesz przejść "przez odniesienie" w C, więc nadal widzisz, że jest używany dość często.

Wskaźnik NULL jest przydatną konwencją do mówienia, że parametr jest nieużywany lub nieprawidłowy, więc użyj wskaźnika w tym przypadku.

Odniesienia nie mogą być aktualizowane po ich ustawieniu, więc użyj wskaźnika, jeśli chcesz je ponownie przypisać.

Preferuj odniesienie w każdym przypadku, gdy nie ma dobrego powodu, aby tego nie robić. Zrób to const jeśli możesz.

 4
Author: Mark Ransom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-20 05:18:40
 4
Author: Rocky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-23 07:28:00

Używaj referencji przez cały czas, a wskaźniki tylko wtedy, gdy musisz odwołać się do NULL, których Referencja nie może się odnosić.

Zobacz ten FAQ : http://www.parashift.com/c++ - faq-lite / referencje. html#faq-8.6

 2
Author: Sanish,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-20 05:26:04