referencja a wskaźnik w funkcji

0

Ok, wiem, że na forum temat był wałkowany ale nadal nie wszystko jest dla mnie jasne, w związku z tym mam 2 pytania.

Czy zwrot referencji do obiektu przez funkcję od zwrotu wskaźnika do tego obiektu różni się tylko tym, że zwracamy stały wskaźnik? Więcej różnic nie znalazłem.

Czy przesyłając do funkcji wskaźnik do jakiegoś obiektu tworzymy kopię takiego adresu i na podstawie kopii możemy zmienić obiekt a przesyłając referencję przesyłamy adres oryginalnego obiektu i na tym obiekcie działamy?

Nie wiem czy dobrze rozumiem ten temat, byłbym wdzięczny za odp :D

2

Zwracając referencję zazwyczaj zwracasz jeden z argumentów funkcji (bo przecież nie referencję do zmiennej lokalnej). Zwracając wskaźnik tak naprawdę zwracasz adres obiektu utworzonego dynamicznie przez new.

Czy przesyłając do funkcji wskaźnik do jakiegoś obiektu tworzymy kopię takiego adresu i na podstawie kopii możemy zmienić obiekt a przesyłając referencję przesyłamy adres oryginalnego obiektu i na tym obiekcie działamy?

Referencja tak jak wskaźnik służy do przesyłania adresu obiektu - o żadnych kopiach nie ma tam mowy. Przy czym referencja jest przezwiskiem i sama referencja nie powie Ci nic o adresie, a wskaźnik zawsze jest adresem.

5

Czy zwrot referencji do obiektu przez funkcję od zwrotu wskaźnika do tego obiektu różni się tylko tym, że zwracamy stały wskaźnik? Więcej różnic nie znalazłem.
Wskaźnik może być nullowy, a referencja nie, więc zwracanie referencji ma mniejszy obszar zastosowań.

Czy przesyłając do funkcji wskaźnik do jakiegoś obiektu tworzymy kopię takiego adresu i na podstawie kopii możemy zmienić obiekt
Tak. Trochę więcej: Przekazywanie parametru przez wartość i referencję

a przesyłając referencję przesyłamy adres oryginalnego obiektu i na tym obiekcie działamy?
Jako że standard nie określa, jak implementowana jest referencja, to tak naprawdę zależy od kompilatora co tutaj się dzieje. W szczególności referencja może być implementowana jako wskaźnik i tak naprawdę masz ten sam mechanizm, tylko ładniejszą składnię.

1

T* foo(/* ... /)
T& bar(/
... */)
Różnic jest więcej.

foo może zwrócić nullptr, co zwykle (praaawie zawsze) traktujesz jako "sentinel value", czyli jako wartość sygnalizującą, że foo nie mogło zwrócić prawidłowego adresu. Jeżeli foo zwróci prawidłowy adres - może to być adres:

  • na jakąś pojedynczą wartość,
  • na wartości (char* na c-string, jakaś inna kolekcja z wartością sygnalizującą, albo tablica, gdzie jej rozmiar dostajesz na przykład przez parametr)
  • przesunięty o jeden element poza pojedynczą wartość lub koniec tablicy. Na takim wskaźniku nie powinieneś robić dereferencji, a dokumentacja powinna Ci powiedzieć, że dostajesz taki specyficzny adres. Jeżeli nie wiesz dlaczego tak mogłoby się stać - pomyśl o standardowych iteratorach w C++.
    Adres zwrócony może pokazywać na pamięć, która jest zarządzana przez kogoś innego w innym miejscu. Jest też możliwość, że zwróci pamięć zaalokowaną przez malloc/calloc/realloc albo new/new[] i przekazuje Ci jej własność - w takim przypadku powinieneś taką pamięć zwolnić za pomocą odpowiednio free() lub delete/delete[]. Dokumentacja takiej funkcji powinna to wyłuszczyć.

bar zwróci referencję do jakiegoś obiektu - czyli bar zawsze jakąś wartość T zwróci, w odróżnieniu od foo. Nie musisz się martwić zarządzaniem pamięci - ktoś się już tym zajmuje.*

Oczywiście, w obydwu przypadkach jeżeli funkcja zwróci adres/referencję zmiennej lokalnej, bum.

Czy przesyłając do funkcji wskaźnik do jakiegoś obiektu tworzymy kopię takiego adresu i na podstawie kopii możemy zmienić obiekt
W zasadzie tak. Jeśli nie przesyłasz czegoś przez referencję, to zawsze przesyłasz to przez kopię - wskaźniki również. Możesz mieć do pierona wskaźników (T*) z adresem na Twój obiekt i dereferencja każdego z tych wskaźników pozwoli Ci na zmianę tego obiektu.

a przesyłając referencję przesyłamy adres oryginalnego obiektu i na tym obiekcie działamy?
E, i tak i nie. Bardziej na nie, ale co "pod spodem" kompilator zrobi to inna sprawa.
Mógłbyś myśleć o referencji jak o "self-dereferencing const pointer to T", problem w tym, że biorąc "adres referencji" dostajesz adres obiektu, a nie tego wyimaginowanego "stałego wskaźnika" - bo i żadnego wskaźnika może tak naprawdę nie być. Nie ma referencji na referencje, ani wskaźników na referencje (ale są wskaźniki na wskaźniki). Referencja to w zasadzie alias, coś jak "przezwisko" jak to xfin napisał.
Referencja to nie obiekt, może zajmować miejsce w pamięci, lub nie. (A to ci efemeryczna bestia :P) Łapiąc obiekt przez referencję w funkcji dostajesz ten właśnie obiekt, ale - znowu - referencja to nie obiekt, więc można zwrócić referencję do lokalnej zmiennej, która to referencja jest nieprawidłowa po powrocie z funkcji. (google "dangling reference", "dangling pointer").
Dziwne? A jednak nie takie rzeczy się fizjonomom... ;)


*) troszkę się krzywię to pisząc... :P

1 użytkowników online, w tym zalogowanych: 0, gości: 1