2009-08-26 7 views
7

Q1. W Javie wszystkie obiekty, tablice i zmienne klasy są przechowywane na stercie? Czy to samo dotyczy C++? Czy segment danych jest częścią Sterty?Pytanie ramki stosu: Java vs C++

Co z następującym kodem w C++?

class MyClass{ 
    private: 
      static int counter; 
      static int number; 
}; 

MyClass::number = 100; 

Q2. O ile mi wiadomo, zmienne, którym nadano określoną wartość przez kompilator, są przechowywane w segmencie danych, a niezainicjalizowane zmienne globalne i statyczne są przechowywane w BSS (Block started by symbol). W tym przypadku licznik MyClass :: static jest inicjalizowany do zera przez kompilator i dlatego jest przechowywany na BSS, a numer MyClass ::, który jest zainicjalizowany na 100, jest przechowywany w segmencie danych. Czy poprawny jest wniosek?

Q3. Rozważmy następujący fragment kodu:

void doHello(MyClass &localObj){ 
// 3.1 localObj is a reference parameter, where will this get stored in Heap or Stack? 
     // do something 
} 

void doHelloAgain(MyClass localObj){ 
// 3.2 localObj is a parameter, where will this get stored in Heap or Stack? 
     // do something 
} 

int main(){ 
     MyClass *a = new MyClass(); // stored in heap 

     MyClass localObj; 
     // 3.3 Where is this stored in heap or stack? 
     doHello(localObj); 
     doHelloAgain(localObj); 
} 

Mam nadzieję, że dokonały moje pytania jasne dla wszystkich

EDIT:

Proszę odnieść to article jakiegoś zrozumienia na BSS

Edit1 : Zmieniono nazwę klasy z MyInstance na MyClass, ponieważ była to zła nazwa. Szczere przeprosiny

EDIT2: Zmieniono liczbę zmienna członka klasy z nie-statyczne do statycznej

+0

każdym razem wywołać 'new', jesteś mallocing, co oznacza, że ​​cokolwiek tworzysz z' new' rzeczywiście przechowywane na stercie. Nie mam pojęcia, co masz na myśli przez "czy segment danych jest częścią Heap?". –

+0

MyClass :: number = 100; nie będzie się kompilować. Czy chodziło Ci o kontratak? –

+0

zmieniono numer zmiennej elementu na statyczny – pankajt

Odpowiedz

6

Jest to nieco uproszczone, ale w większości zgodne z moją najlepszą wiedzą.

W Javie wszystkie obiekty są przydzielane na stercie (w tym wszystkie zmienne składowe). Większość innych rzeczy (parametrów) to referencje, a same referencje są przechowywane na stosie razem z rodzimymi typami (int, longs, itp.) Za wyjątkiem łańcucha, który jest bardziej obiektem niż rodzimym typem.

W C++, gdybyś przydzielił wszystkie obiekty za pomocą słowa kluczowego "new", byłaby to prawie taka sama sytuacja jak java, ale jest jeden wyjątek w C++, ponieważ możesz przydzielić obiekty na stosie (ty nie zawsze muszą używać "nowego").

Należy również zauważyć, że wydajność sterty Java jest bliższa wydajności stosu C niż wydajność sterty C, a garbage collector robi całkiem sprytne rzeczy. Wciąż nie jest tak dobry jak stos, ale znacznie lepszy niż kupa. Jest to konieczne, ponieważ Java nie może przydzielać obiektów na stosie.

+0

ładne informacje o wydajności sterty java i porównaniu wydajności stosów c – pankajt

+0

Wszystkie obiekty Java są przechowywane w stercie, tak. Zmienne obiektów przechowują odwołania do nich. Pierwotne zmienne (int, float, bool itp.) Przechowują własne wartości; nie są referencjami. Parametry metody są przekazywane według wartości. –

+0

W tym momencie naprawdę pogardzam całym przełęczem terminologią wartości/odniesienia i staram się go nie używać. W Javie najłatwiej jest tylko pamiętać, że kiedy mamy do czynienia z obiektami, zawsze mamy odnośnik, nigdy nie przekazujemy rzeczywistego obiektu. Powiedzieć, że to nie jest "Przekaż przez odniesienie", dezorientuje wszystkich, którzy próbują zrozumieć, jak działa ten język (nawet jeśli to prawda), więc całkowicie porzuciłem terminologię. –

2

Q1

Java przechowuje również zmienne na stosie, ale instancje klasy są alokowane na stercie. W C++ możesz dowolnie alokować instancje klasy na stos lub na stercie. Za pomocą słowa kluczowego new alokujesz wystąpienie na stercie.

Segment danych nie jest częścią sterty, ale jest alokowany, gdy proces się rozpocznie. Sterta jest używana do dynamicznego przydzielania pamięci, podczas gdy segment danych jest statyczny, a zawartość jest znana podczas kompilacji.

Segment BSS to po prostu optymalizacja, w której wszystkie dane należące do segmentu danych (np. Ciąg, numery stałe itp.), Które nie zostały zainicjowane lub zainicjowane do zera, są przenoszone do segmentu BSS. Segment danych musi być osadzony w pliku wykonywalnym i poprzez przeniesienie "wszystkich zer" do końca mogą zostać usunięte z pliku wykonywalnego. Po załadowaniu pliku wykonywalnego segment BSS zostaje przydzielony i zainicjowany do zera, a kompilator nadal może znać adresy różnych buforów, zmiennych itp. Wewnątrz segmentu BSS.

Q2

MyClass::number są przechowywane gdzie wystąpienie MyClass klasie jest przydzielona. Może być na stosie lub na stosie. Zauważ w Q3, jak a wskazuje instancję MyClass przydzieloną do sterty, podczas gdy localObj jest przydzielana na stosie. Tak więc a->number znajduje się na stercie, podczas gdy localObj.number znajduje się na stosie.

Jak MyClass::number jest zmienną instancji nie można przypisać to tak:

MyClass::number = 100; 

Jednak można przypisać MyClass::counter jak to jest statyczny (chyba, że ​​jest to prywatny):

MyClass::counter = 100; 

Q3

Po wywołaniu doHello zmienna localObj (w main) jest przekazywane przez odniesienie. Zmienna localObj w doHello odnosi się do tej zmiennej na stosie. Jeśli go zmienisz, zmiany zostaną zapisane na stosie, gdzie przydzielono localObj w main.

Po wywołaniu doHelloAgain zmienna localObj (w main) jest kopiowana na stos. Wewnątrz doHelloAgain zmienna localObj jest przydzielana na stosie i istnieje tylko przez czas trwania połączenia.

+0

Q3: Odnośniki, podobnie jak wskaźniki, są 32-bitowymi (zwykle) wartościami przechowującymi adres pamięci. To dzieje się na stosie w DoHello. Klasa "MyInstance" ma 8 bajtów (zakładając, że int jest 32-bitowe), i idzie na stos w doHelloAgain. –

1

Q1. W języku Java wszystkie obiekty, tablice i zmienne klasy są przechowywane na stertach ? Czy to samo dotyczy C++? Czy segment danych jest częścią Sterty?

Nie, sekcja danych jest oddzielona od sterty. Zasadniczo, sekcja danych jest przydzielana w czasie ładowania, wszystko co ma ustaloną lokalizację po tym. Ponadto obiekty mogą być przydzielane na stosie.

Obiekty jednorazowe znajdują się na stercie, jeśli użyto słowa kluczowego new lub jeśli użyto czegoś z rodziny funkcji malloc.

Q2. Jeśli chodzi o moje rozumowanie, zmienne, które mają określoną wartość przez kompilator, są przechowywane w segmencie danych , a niezainicjalizowane globalne i statyczne zmienne są przechowywane w BSS (Blok rozpoczęty przez symbol). W tym przypadku, MyInstance :: licznik jest static jest inicjowany do zera przez kompilator i tak jest on przechowywany w BSS i MyInstance :: numer, który jest inicjowane 100 jest przechowywany w segmencie danych. Czy mam rację podając wniosek?

Tak, twoje zrozumienie sekcji BSS jest poprawne. Jednakże, ponieważ number nie jest statyczna kod:

MyInstance::number = 100; 

nie jest legalny, musi być wykonana zarówno statyczne lub zainicjowany w konstruktorze prawidłowo. Jeśli zainicjujesz go w konstruktorze, będzie on istnieć wszędzie tam, gdzie przydzielany jest obiekt będący właścicielem. Jeśli sprawisz, że będzie statyczny, przejdzie do sekcji danych ... jeśli gdziekolwiek. Często zmienne static const int można wstawiać bezpośrednio do kodu używanego w taki sposób, że zmienna globalna w ogóle nie jest potrzebna.

Q3. Rozważ następujące fragmenty kodów: ...

void doHello(MyInstance &localObj){

localObj jest odniesienie do Przekazany obiekt. O ile wiesz, nie ma pamięci, odnosi się do tego, gdzie jest przekazywana zmienna. W rzeczywistości, pod maską, wskaźnik może być przekazany na stos, aby to ułatwić. Ale kompilator może równie łatwo zoptymalizować, jeśli to możliwe.

void doHelloAgain(MyInstance localObj){

kopia z przekazanym parametrem jest umieszczany na stosie.

MyInstance localObj; 
// 3.3 Where is this stored in heap or stack? 

localObj jest na stosie.

+0

"obiekty mogą być przydzielane na stosie" Zgadzam się z tym, ale czy to samo dotyczy java? – pankajt

+3

Nie, java alokuje prymitywy i odniesienia na stosie, a nie obiektach. – nos

1

W C++ obiekty mogą być przydzielane na stosie ... na przykład localObj w głównej procedurze Q3.

Wyczuwam pewne zamieszanie związane z klasami a instancjami. "MyInstance" ma więcej sensu jako nazwa zmiennej niż nazwa klasy. W twoim przykładzie z przykładu Q1 "liczba" występuje w każdym obiekcie typu MyInstance. "licznik" jest współdzielony przez wszystkie instancje. "MyInstance :: counter = 100" jest poprawnym przydziałem, ale "MyInstance :: number = 100" nie jest, ponieważ nie podałeś , do którego obiektu powinien być przypisany jego "numer".

1

Wszystkie obszary pamięci w C++ są wymienione here