Wątek przeniesiony 2021-06-04 09:53 z Python przez Shalom.

Referencja - głupie pytanie

0

Ostatnio coraz bardziej zastanawiam się czym jest referencja. Czy ona różni się względem wskaźnika?

Można powiedzieć, że referencja to taki wskaźnik, który zlicza odwołania, ale w C++ też są inteligencje wskaźniki. To nadal wskaźniki, a nie referencje.

O ile wskaźnik pozwala wysłuskać adres, wspiera arytmetykę na wskaźnikach, umożliwia wyrażenie wskaźnika na wskaźnik, a referencja tak niezbyt.

O ile rozumiem, że obie konstrukcje służą po to, aby móc odwoływać się do czegoś co istnieje, ale tak nie rozumiem czemu tutaj mamy dwie osobne nazwy, jakby zupełnie co innego oznaczały..

W przypadku baz danych to jest prostsze do pojęcia, bo jak piszę w FK ze słowem "references" to wiem, że tu nie tylko chodzi o wskazanie (bo wskazać mógłbym w oparciu o sam surowy integer), ale również chodzi o zachowanie pewnego poziomu integralności, spójności w obrębie dokonywanych działań, blokad itp.

A wy jak to rozumiecie? Czy javowa referencja też dba o jakąś spójność? Może po prostu czegoś fundamentalnego jeszcze nie wiem :-)

5

Po pierwsze to pytanie być powinno czym się różni wskaźnik od referencji.
Referencja to po prostu "uchwyt" na obiekt. Pozwala zobaczyć ten sam obiekt pod różnymi nazwami. W zasadzie koniec - czy te referencje są liczone i jakoś tam bezpieczne w użyciu to zupełnie ortogonalna sprawa.

Osobną sprawą jest wskaźnik - można powiedzieć, że wskaźnik to taka zniszczona, zdeprawowana, pokaleczona referencja. Przyszło to to z językiem C i jest takim dziwnym typem, przez który z języka niby wysokiego poziomu wystaje Ci maszyna. Jest to dramat (zwłaszcza, że duża części operacji na wskaźnikach (rzutowania) to UB, który tylko przypadkiem działa) , ale poniekąd przy pisaniu systemu operacyjnego przydatne.

Używanie wskaźników w C++, jeśli nie piszesz systemu operacyjnego, i nie robisz czegoś nieskopoziomowego to IMO słaby pomysł.
Javowe referencje też nie są idealne, bo pozwalają na null.

0

Na wiki masz to też dość dobrze wyjaśnione:

https://pl.wikipedia.org/wiki/Wska%C5%BAnik_(typ_danych)

1

"Sprytne wskaźniki" w C++ to nie są wskaźniki, tylko obiekty, które zarządzają cyklem życia wskaźnika, który przechowują. Zachowanie jest różne, w zależności od potrzeb, ale najbardziej spektakularnym jest zliczanie miejsc w których jest używany dany smart pointer. Jak liczba odwołań spadnie do 0, to takie pudełko na wskaźnik zwalnia pamięć na którą wskazuje przechowywany wewnątrz wskaźnik. Czyli funkcjonalnie jest to odpowiednik Java garbage collector w C++, chociaż działający w kompletnie inny sposób.

We współczesnych językach wysokiego poziomu, wskaźniki praktycznie nie występują (albo odradza się ich stosowanie). Wskaźnik, to najprościej mówiąc adres w pamięci operacyjnej, gdzie "coś" się znajduje (gdzie zaczyna się obiekt). Nie wiesz do końca co, nie wiesz, czy jeszcze istnieje, jak stracisz wskaźnik, to pamięć wciąż pozostaje zajęta (czyli mamy wyciek pamięci).

Referencja w przypadku Javy działa trochę podobnie, ma mniejsze możliwości. Np. nie możesz przekształcić jej na 8 bajtów adresu w pamięci, nie możesz do niej dodać iluś tam bajtów i uzyskać wskaźnik na kolejny element tablicy. Generalnie nie możesz robić masy rzeczy, które możesz robić ze wskaźnikiem i które w 1% przypadków dają coś sensownego, a w 99% nie pozwalają przeczytać tego co robi program.

Generalnie wszystko zależy od języka. Masz języki gdzie są wyłącznie wskaźniki (asm), masz takie gdzie masz wskaźniki i referencje (C++), masz też takie, gdzie są wyłącznie referencje (Java). W C++ jest to zmienna możliwa do przypisania wyłącznie raz, w momencie unicestwienia zmiennej, niszczony jest również obiekt w pamięci.

0

Tak sobie myślę i jedna z rzeczy jaka robi różnicę to fakt, że wskaźnik w dowolnym momencie może od tak zaorać obiekt w pamięci.

Podczas gdy referencja, nie ma takiej władzy, jest bardziej przewidywalna, ponieważ traktuje obecność uchwyconego obiektu jako coś stałego.

1

@pan_krewetek: Nie. Wskaźnik to fizyczny adres w pamięci RAM gdzie znajdują się dane. Referencja to abstrakcja. Wiesz, że tam jest jakiś obiekt i więcej cię nie obchodzi. W takim C++ możesz sobie wziąć wskaźnik, rzutować na typ liczbowy, dodać do niego 5 i znowu przerobić na wskaźnik, który przy odrobinie szczęścia wskaże coś istniejącego.

0

Moim zdaniem, wskaźnik w C++ i referencja w Java różnią się tylko takimi właściwościami:

  1. Pod wskaźnikiem jest liczba będąca adresem w pamięci i można na niej operować (jednak w 99% przypadków ta cecha nie jest wykorzystywana i nie jest ważna wartość tej liczby).
  2. Referencja może być albo pusta (null), albo wskazywać obiekt, natomiast wskaźnik może wskazywać na przypadkowe miejsce i próba jakiejkolwiek czynności na takim wskaźniku jest UB.
  3. Jak wskazywany obiekt przestaje istnieć (w C++ jest możliwe zniszczenie obiektu przed końcem istnienia samego wskaźnika, w Javie nie jest to możliwe), to wszystkie wskaźniki zachowują dotychczasową wartość i próba odwołania się do obiektu jest UB.
  4. W przypadku tablicy, w Javie jest tablica jako obiekt, a w C++ tablica jest ciągiem wartości zajmujących kolejne bajty w pamięci i odwołanie się do któregoś elementu tablicy jest tym samym, co odwołanie się do pamięci wskazywanej przez wskaźnik zwiększony o wartość będącą iloczynem numeru elementu i wielkości elementu tablicy, jest to powodem, dlaczego próba odwołania się do elementu <0 lub >=wielkość tablicy jest UB, a nie jednoznacznym błędem. Jednak w 99% przypadków świadomość takiej cechy wskaźnika nie jest potrzebna, w obu językach zapis odwołania się do elementu tablicy jest taki sam, tylko trzeba pilnować, aby nie wychodzić poza zakres tablicy.

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