Pass-by-value, pass-by-reference, memory model

0

Przeczytałem kilka artykułów, odpowiedzi ze Stacka, obejrzałem kilka filmików na YT i nadal nie mam pewności czy dobrze rozumiem jak działa pamięć w Javie i czy Java jest pass-by-value cyz pass-by-reference, tak więc prosiłbym o potwierdzenie ;)

  • Mamy dwa typy danych - primitives i reference types.
  • Te pierwsze, jeżeli stworzone lokalnie, są przechowywane na stosie. Poniższy kod stworzy dwa osobne elementy na stosie.
int a = 3;
int b = a;

Jeżeli napiszę teraz b = 5, zmienie tylko wartość zmiennej b, zmienna a pozostanie równa 3.

  • Te drugie, na stosie przechowywują wskaźnik do faktycznej wartości obiektu na stercie. Poniższy kod stworzy na stosie dwa wskaźniki do tej samej wartości na stercie:
User john = new User("john");
User jack = john;

Oznacza to, że jack.name = "Jack" spowoduje zmianę w zmiennej john i jack

  • Przekazanie czegokolwiek do funkcji, powoduje stworzenie kopii przekazanej wartości, tak więc wszystkie zmiany jakie zrobie wewnątrz funkcji, nie zmodyfikują oryginalnego argumentu. Jednakże, analogiczne jak w powyższych przykładach, przekazanie primitywnego typu, powoduje stworzenie jego kopii na stosie, więc faktycznie zmiana czegoś wewnątrz funkcji wpłynie tylko na kopie. Z drugiej strony, przekazanie obiektu, spowoduje stworzenie na stosie kopii wskaźnika, który jednak wskazuje na tę samą referencę na stercie. Dlatego też, zmiana właściwości kopii tego obiektu, zostanie również zaaplikowana do oryginalnego obiektu.

  • Jako, że Java jest pass-by-value, oznacza to że value to adres konkretnego bytu, a reference to jego faktyczna wartość?

  • Co faktycznie jest przechowywane na stosie w przypadku typów primitywnych?

0

tutaj chyba jest jasno wytłumaczone: https://community.oracle.com/tech/developers/discussion/2110675/pass-by-reference-or-pass-by-value

There is no such thing as pass by reference in Java. Once again you do not seem to understand that the object is not passed. The variable "obj" is not an object, it is a reference. The value is copied, this is pass by value. Because it is copied both variables point to the same instance of class A. You are then modifying that object's instance variables, you're not actually changing the variable passed.

1

@Gazel: Prawie dobrze. Wskaźnik to mniej więcej to samo co referencja w tym sensie, że oba zawierają adres. W Javie nie używa się pojęcia wskaźnika, jest tylko pojęcie referencji do obiektu (ale jak ktoś użyje słowa wskaźnik to też wiadomo, że chodzi o to samo co z referencją). Z tego względu stwierdzenie typu:

Z drugiej strony, przekazanie obiektu, spowoduje stworzenie na stosie kopii wskaźnika, który jednak wskazuje na tę samą referencę na stercie.

.. jest co najmniej błędne. Referencja wskazuje na instancję obiektu na stercie. Takiej terminologii się w Javie używa.

0

@Wibowit:

.. jest co najmniej błędne. Referencja wskazuje na instancję obiektu na stercie. Takiej terminologii się w Javie używa.

Właśnie to mnie myli ;)

  • Czyli na stosie trzymamy referencje (adres) obiektu który znajduje się na stercie?
  • Do fukcji przekazujemy referencje (adres) obiektu, następnie tworzona jest kopia tej referencji, która jednak nadal odnosi się do tego samego obiektu na stercie?

Czemu więc to się nazywa pass-by-value, skoro przekazujemy referencje... :D ?

2

C++, pass-by-reference

https://replit.com/@stivens/DeadInterestingInsurance#main.cpp

Java, pass-by-value (w szczegolnym przypadku wartoscia jest referencja)

https://replit.com/@stivens/ForcefulInternalRuntimes#Main.java


Roznice chyba widac po wywolaniu? :)

8

Czyli na stosie trzymamy referencje (adres) obiektu który znajduje się na stercie?

Tak

Do fukcji przekazujemy referencje (adres) obiektu, następnie tworzona jest kopia tej referencji, która jednak nadal odnosi się do tego samego obiektu na stercie?

Tak

Czemu więc to się nazywa pass-by-value, skoro przekazujemy referencje... :D ?

Bo przekazujesz referencję przez wartość :] W C/ C++/ Ruście/ etc można mieć wskaźnik do wskaźnika do wskaźnika etc, a więc można np. przekazać wskaźnik przez wskaźnik i czasami tak się robi przy wywołaniach funkcji bibliotecznych.

Inaczej mówiąc:

  • pass-by-value oznacza, że argument jest kopiowany - jeśli jest to prymityw to kopiujemy prymityw, jeśli jest to referencja to kopiujemy referencję. W Javie nie ma zmiennych przechowujących obiekty (przynajmniej tych z tożsamością, bo po wprowadzeniu Project Valhalla będzie można zrobić obiekt prymitywny, ale to przyszłość), więc nie ma kopiowania obiektów.
  • pass-by-reference oznacza, że argument nie jest kopiowany, a za to w docelowej metodzie otrzymujemy referencję do niego i możemy dzięki temu modyfikować oryginalny argument. W Javie tego nie ma. Jeśli zrobię wywołanie metodaA(lokalnaZmienna1, lokalnaZmienna2); to po powrocie z tej metody zmienne lokalnaZmienna1 i lokalnaZmienna2 będą na 100% miały taką samą zawartość jak przed wywołaniem (czyli będą miały tą samą wartość prymitywną lub ten sam adres co wcześniej).

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