2009-08-26 18 views
7

Q1. En Java, tous les objets, tableaux et variables de classe sont stockés sur le tas. Est-ce la même chose pour C++? Le segment de données fait-il partie de Heap?Stack Frame Question: Java vs C++

Qu'en est-il du code suivant en C++?

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

MyClass::number = 100; 

Q2. Autant que je sache, les variables auxquelles une valeur spécifique est donnée par le compilateur sont stockées dans le segment de données, et les variables globales et statiques non initialisées sont stockées dans BSS (Block started by symbol). Dans ce cas, MyClass :: counter étant statique est initialisé à zéro par le compilateur et donc il est stocké dans BSS et MyClass :: number qui est initialisé à 100 est stocké dans le segment de données. Ai-je raison de conclure?

Q3. Tenez compte suivant morceau de code:

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); 
} 

J'espère avoir fait mes questions claires à tous

EDIT:

S'il vous plaît se référer ce article pour une certaine compréhension sur BSS

EDIT1 : Changé le nom de classe de MyInstance à MyClass car c'était un nom médiocre. Sincère Toutes mes excuses

EDIT2: Changé le membre de la classe nombre variable de non-statique statique

+0

Chaque fois que vous appelez 'new', vous êtes allouer de, ce qui signifie que tout ce que vous créez avec' new' est en effet stocké sur le tas. Je n'ai aucune idée de ce que vous entendez par "le segment de données fait-il partie de Heap?". –

+0

MyClass :: number = 100; ne compilera pas. Voulez-vous dire contre? –

+0

numéro de variable membre modifié en statique – pankajt

Répondre

6

Ceci est quelque peu simplifié mais surtout précis au meilleur de ma connaissance.

En Java, tous les objets sont alloués sur le tas (y compris toutes vos variables membres). La plupart des autres choses (paramètres) sont des références, et les références elles-mêmes sont stockées sur la pile avec des types natifs (ints, longs, etc) sauf une chaîne qui est plus un objet qu'un type natif. En C++, si vous alliez allouer tous les objets avec le mot-clé "new", ce serait à peu près la même situation que java, mais il y a un cas unique en C++ car vous pouvez allouer des objets sur la pile (vous ne pas toujours utiliser "nouveau").

Notez également que les performances de tas de Java sont plus proches des performances de la pile de C que les performances de tas de C, le garbage collector fait des choses assez intelligentes. Ce n'est toujours pas aussi bon que pile, mais beaucoup mieux qu'un tas. Ceci est nécessaire car Java ne peut pas allouer d'objets sur la pile.

+0

nice info sur les performances de tas de java et la comparaison des performances de la pile c – pankajt

+0

Tous les objets Java sont stockés dans le tas, oui. Les variables d'objet stockent des références à celles-ci. Les variables primitives (int, float, bool, etc) stockent leurs propres valeurs; ce ne sont pas des références. Les paramètres de méthode sont transmis par valeur. –

+0

À ce stade, je méprise vraiment tout le passage par la terminologie valeur/référence et essayez de ne pas l'utiliser. En Java, il est plus facile de se rappeler que lorsque vous travaillez avec des objets, vous avez toujours une référence, vous ne passez jamais l'objet réel. Dire que ce n'est pas "Passer par la référence" confond l'enfer de quiconque essaie de comprendre comment la langue fonctionne (même si c'est vrai) alors j'ai complètement abandonné la terminologie. –

2

Q1

Java stocke également des variables sur la pile, mais les instances de classe sont attribués sur le tas. En C++, vous êtes libre d'allouer vos instances de classe soit sur la pile, soit sur le tas. En utilisant le mot-clé new vous allouez l'instance sur le tas.

Le segment de données ne fait pas partie du tas, mais est alloué au démarrage du processus. Le tas est utilisé pour les allocations de mémoire dynamique alors que le segment de données est statique et que le contenu est connu au moment de la compilation.

Le segment BSS est simplement une optimisation dans laquelle toutes les données appartenant au segment de données (chaîne, nombres constants, etc.) qui ne sont pas initialisées ou initialisées à zéro sont déplacées vers le segment BSS. Le segment de données doit être intégré dans l'exécutable et en déplaçant "tous les zéros" à la fin, ils peuvent être supprimés de l'exécutable. Lorsque l'exécutable est chargé, le segment BSS est alloué et initialisé à zéro, et le compilateur peut toujours connaître les adresses des différents tampons, variables, etc., à l'intérieur du segment BSS.

Q2

MyClass::number où est stockée l'instance de classe MyClass est alloué. Il pourrait être sur le tas ou sur la pile. Notez au Q3 comment a pointe vers une instance de MyClass allouée sur le tas tandis que localObj est allouée sur la pile. Ainsi, a->number est situé sur le tas tandis que localObj.number se trouve sur la pile.

Comme MyClass::number est une variable d'instance, vous ne pouvez pas affecter comme ceci:

MyClass::number = 100; 

Cependant, vous pouvez affecter MyClass::counter comme il est statique (sauf qu'il est privé):

MyClass::counter = 100; 

Q3

Lorsque vous appelez doHello la variable localObj (dans main) est passé par référence. La variable localObj dans doHello renvoie à cette variable sur la pile. Si vous le modifiez, les modifications seront stockées sur la pile où localObj dans main est allouée.

Lorsque vous appelez doHelloAgain, la variable localObj (dans main) est copiée dans la pile. À l'intérieur doHelloAgain la variable localObj est allouée sur la pile et n'existe que pour la durée de l'appel.

+0

Q3: Les références, comme les pointeurs, sont des valeurs de 32 bits (généralement) qui contiennent une adresse mémoire. Cela va sur la pile dans doHello. La classe "MyInstance" est de 8 octets (en supposant que int est de 32 bits), et il va sur la pile dans doHelloAgain. –

1

Q1. En Java, tous les objets, tableaux et variables de classe sont stockés sur le tas ? Est-ce la même chose pour C++? Le segment de données fait-il partie de Heap?

Non, la section de données est séparée du tas. Fondamentalement, la section de données est allouée au moment du chargement, tout ce qu'il y a un emplacement fixe après cela. De plus, les objets peuvent être alloués sur la pile.

Les seuls objets de temps sont sur le tas si vous utilisez le mot-clé new ou si vous utilisez quelque chose de la famille de fonctions malloc.

Q2. Pour autant que je le sache, variables qui reçoivent une valeur spécifique par compilateur sont stockés dans le segment de données , et les variables statiques globales non initialisées et sont stockées dans BSS (Bloc démarré par le symbole). Dans ce cas , MyInstance :: compteur étant statique est initialisée à zéro par le compilateur et il est donc stocké à BSS et MyInstance :: nombre qui est initialisé à 100 est stocké dans le segment de données . Ai-je raison de faire la conclusion?

Oui, votre compréhension de la section BSS est correcte. Cependant, étant donné que number n'est pas statique le code:

MyInstance::number = 100; 

est pas légal, il doit être soit en statique ou initialisé dans le constructeur correctement. Si vous l'initialisez dans le constructeur, il existera partout où l'objet propriétaire est alloué. Si vous le rendez statique, il finira dans la section de données ... si vous voulez. Souvent, les variables static const int peuvent être insérées directement dans le code utilisé de telle sorte qu'une variable globale n'est pas nécessaire du tout.

Q3. Considérez le morceau de code suivant: ...

void doHello(MyInstance &localObj){

localObj est une référence à l'objet passé. Pour autant que vous le sachiez, il n'y a pas de stockage, il se réfère à l'endroit où la variable est passée. En réalité, sous le capot, un pointeur peut être passé sur la pile pour faciliter cela. Mais le compilateur peut tout aussi bien optimiser cela s'il le peut.

void doHelloAgain(MyInstance localObj){

une copie du paramètre transmis est placé sur la pile.

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

localObj est sur la pile.

+0

"les objets peuvent être alloués sur la pile" Je suis d'accord avec ça, mais est-ce la même chose dans le cas de java? – pankajt

+3

Non, java n'alloue que des primitives et des références sur la pile, pas des objets. – nos

1

En C++, des objets peuvent être alloués sur la pile ... par exemple, localObj dans votre routine principale Q3.

Je sens une certaine confusion à propos des classes par rapport aux instances. "MyInstance" a plus de sens en tant que nom de variable que nom de classe. Dans votre exemple Q1, "nombre" est présent dans chaque objet de type MyInstance. "counter" est partagé par toutes les instances. "MyInstance :: counter = 100" est une affectation valide, mais "MyInstance :: number = 100" ne l'est pas, car vous n'avez pas spécifié auquel l'objet doit avoir son membre "number".

1

Toutes les zones de mémoire en C++ sont répertoriés here