7
votes

Stack Cadre Question: Java vs C ++

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

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

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


3 commentaires

Chaque fois que vous appelez nouveau , vous êtes mallocing, ce qui signifie que tout ce que vous créez avec nouveau est bien stocké sur le tas. Je n'ai aucune idée de ce que vous entendez par "Le segment de données est une partie du tas?".


MyClass :: Numéro = 100; ne compilera pas. Avez-vous voulu compter contre?


Numéro de variable modifié des membres à statique


5 Réponses :


2
votes

q1

Java stocke également des variables sur la pile, mais des instances de classe sont allouées sur le tas. En C ++, vous êtes libre d'attribuer vos instances de classe sur la pile ou sur le tas. En utilisant le mot-clé neuf , vous allouez l'instance sur le tas.

Le segment de données ne fait pas partie du tas, mais est alloué lorsque le processus commence. Le tas est utilisé pour des allocations de mémoire dynamiques, tandis que le segment de données est statique et le contenu est connu à l'heure de la compilation.

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

q2 < / strong>

myClass :: Number est stocké lorsque l'instance de myClass est attribuée. Cela pourrait être sur le tas ou sur la pile. AVIS DANS Q3 Comment A Points à une instance de MyClass attribué sur le tas tandis que localobj est attribué sur la pile. Ainsi, a-> numéro est situé sur le tas lorsque localobj.number est situé sur la pile.

comme myClass :: Number < / Code> est une variable d'instance que vous ne pouvez pas l'affecter comme ceci: xxx

Cependant, vous pouvez affecter myClass :: compteur telle qu'elle est statique ( Sauf que c'est privé): xxx

q3

Lorsque vous appelez DOHELLO la variable localobj (dans principal ) est passé par référence. La variable localobj in Dohello renvoie à cette variable sur la pile. Si vous modifiez cela, les modifications seront stockées sur la pile où localobj dans principal est alloué.

Lorsque vous appelez DOHELLOAGAIN La variable localobj (dans principal ) est copiée sur la pile. Intérieur Dohelloagain La variable localobj est allouée sur la pile et n'existe que pendant la durée de l'appel.


1 commentaires

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



1
votes

Q1. En Java, tous les objets, les tableaux et Les variables de classe sont stockées sur le tas? Est la même chose vraie pour C ++? Est segment de données une partie de tas?

Non, la section de données est séparée du tas. Fondamentalement, la section de données est allouée à temps de charge, tout ce qu'il existe un emplacement fixe après cela. De plus, des objets peuvent être alloués sur la pile.

Les seuls objets de temps sont sur le tas, c'est si vous utilisez le mot-clé neuf ou si vous utilisez quelque chose dans le malloc famille de fonctions.

Q2. En ce qui précède mon compréhension, variables qui reçoivent un spécifique la valeur par compilateur sont stockées dans des données segment et inticulé global et Les variables statiques sont stockées dans BSS (Bloc démarré par le symbole). Dans ce Cas, MyInstance :: Counter Statique est initialisé à zéro par le compilateur et donc il est stocké chez BSS et MyInstance :: Numéro qui est initialisé à 100 est stocké dans la 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 numéro n'est pas statique le code: xxx

n'est pas légal, il doit être soit fait statique, soit initialisé dans le constructeur correctement. Si vous l'initialisez dans le constructeur, il existera partout où l'objet de possession est attribué. Si vous le faites statique, cela se retrouvera dans la section de données ... Si n'importe où. Souvent statique const int variables peut être inlincé directement dans le code utilisé de manière à ce qu'une variable globale ne soit pas nécessaire du tout.

Q3. Pensez à suivre les codes suivants: ...

Void Dohello (MyInstance & localobj) {

localobj est une référence à l'objet transmis. Pour autant que vous sachiez, il n'y a pas de stockage, il fait référence à l'endroit où la variable est passée est. En réalité, sous la hotte, un pointeur peut être transmis sur la pile pour faciliter cela. Mais le compilateur peut tout aussi facilement optimiser cela si cela peut.

Void Dohelloagain (myInstance localobj) {

A > du paramètre transmis est placé sur la pile. xxx

localobj est sur la pile.


2 commentaires

"Les objets peuvent être alloués sur la pile" Je suis d'accord avec ça, mais est-ce la même chose en cas de Java?


Non, Java attribue uniquement des primitives et des références sur la pile, pas des objets.



1
votes

en C ++, des objets peuvent être alloués sur la pile ... Par exemple, localobj dans votre routine principale Q3.

Je sens une certaine confusion sur les classes par rapport aux cas. "MyInstance" a plus de sens comme nom de variable qu'un nom de classe. Dans votre exemple Q1, "numéro" est présent dans chaque objet de type myInstance. "Compteur" est partagé par toutes les instances. "MyInstance :: compteur = 100" est une affectation valide, mais "myInstance :: Number = 100" n'est pas, car vous n'avez pas spécifié quel objet devrait avoir son membre "nombre" attribué à.


0 commentaires

6
votes

Ceci est un 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 de membre). 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 ainsi que des types natifs (INTS, LIPS, etc.), à l'exception de la chaîne qui est plus d'un objet qu'un type natif.

en C ++, si vous alliez allouer tous les objets avec le mot-clé "Nouveau", il 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 pouvez pas 't toujours avoir à utiliser "nouveau").

Notez également que les performances du tas de Java sont plus proches de la performance de la pile de C que de C de la performance du tas de C, le collecteur des ordures fait des trucs assez intelligents. Ce n'est toujours pas aussi bon que la pile, mais bien mieux qu'un tas. Ceci est nécessaire car Java ne peut pas allouer des objets sur la pile.


4 commentaires

De belles informations sur la performance du tas de Java et la comparaison de performances de la pile de C


Tous les objets Java sont stockés dans le tas, oui. Les variables d'objet stockent les références. Les variables primitives (int, flotteur, bool, etc.) stockent leurs propres valeurs; Ce ne sont pas des références. Les paramètres de la méthode sont passés par la valeur.


À ce stade, je méprise vraiment toute la réussite par la terminologie de valeur / de référence et essayez de ne pas l'utiliser. En Java, il est plus facile de rappeler que lorsque vous traitez avec des objets, vous avez toujours une référence, vous ne transmettez jamais l'objet réel. Pour dire que cela n'est pas "Pass par référence" confond à l'enfer de quiconque tente de comprendre comment la langue fonctionne (même si c'est vrai), donc j'ai complètement abandonné la terminologie.


@Devil Jin Yeah, la façon dont Java, l'allocation de tas ne nécessite aucune action par répartition pour libérer la mémoire pour des objets de courte durée (ce qui est juste la manière de la répartition de la pile - un seul "retour" apparaît tous les objets de la pile à une fois). Il y a des papiers blancs qui font de très belles lectures.



1
votes

Toutes les zones de mémoire en C ++ sont répertoriées ici


0 commentaires