web-dev-qa-db-fra.com

Création d'objets sur la pile / tas?

Le code suivant crée un objet sur la pile:

Object o;

Lors de la création d'un objet sur le tas, nous pouvons utiliser:

Object* o;

o = new Object();

plutôt que:

Object* o = new Object();

Lorsque nous divisons la création d'objet de tas sur deux lignes et appelons le constructeur sur la deuxième ligne (o = new object()), cela signifie-t-il que dans la première ligne (Object* o) Le pointeur a été créé sur le empiler? Donc Object o Place l'objet sur la pile, alors que Object* o Place le pointeur sur un futur objet sur la pile?

Ma deuxième question concerne si les deux lignes de code ont été appelées en dehors d'une classe. J'ai lu récemment ( Gestion de la mémoire globale en C dans la pile ou le tas? ) que les variables globales ne sont pas contenues dans la pile/le tas mais en fait une autre partie de la mémoire? Si tel est le cas, Object* o Créerait-il un pointeur qui se trouverait dans cette autre partie de la mémoire et pointe vers l'objet de tas?

46
user997112

En fait, aucune instruction ne dit rien sur le tas ou la pile:

Object o;

crée un objet avec automatique stockage, ce qui signifie que l'emplacement de stockage est déterminé par le contexte dans lequel l'objet est déclaré: Si le code est dans une fonction, cela se trouve être la pile d'appels. Mais la ligne peut également être un membre de la classe ou, comme vous l'avez noté, en dehors d'une fonction/classe.

Pour illustrer pourquoi c'est différent:

struct Foo {
    Object o;
};

Foo* pf = new Foo();

Maintenant, l'objet pf->o est créé sur le tas, pas sur la pile, même si (ou plutôt parce que) il a un stockage automatique.

Inversement,

Object* p;

déclare simplement un pointeur, rien de plus. Le stockage de pointeur ne se distingue pas de tout autre objet: il a un stockage automatique. De plus, l'expression d'initialisation n'a aucun effet sur le stockage variable.

Ce que pointe le pointeur est une question complètement différente. Il peut s'agir d'un objet alloué en tas (en utilisant new par exemple) ou il peut pointer vers un autre objet alloué automatiquement. Considérer:

Object o;
Object* p = &o;
87
Konrad Rudolph

C++ propose trois façons différentes de créer des objets:

  1. Basé sur la pile, comme les objets temporaires
  2. Basé sur le tas en utilisant nouvea
  3. Allocation de mémoire statique telle que les variables globales et les objets de portée d'espace de noms

Considérez votre cas,

Object* o;
o = new Object();

et:

Object* o = new Object();

Les deux formes sont identiques. Cela signifie qu'une variable de pointeur o est créée sur la pile (supposez que vos variables n'appartiennent pas à la catégorie 3 ci-dessus) et qu'elle pointe vers une mémoire dans le tas, qui contient l'objet.

10
DML

Les deux formulaires sont identiques à une exception près: temporairement, le nouveau (Object *) a une valeur indéfinie lorsque la création et l'affectation sont distinctes. Le compilateur peut les regrouper, car le pointeur non défini n'est pas particulièrement utile. Cela ne concerne pas les variables globales (sauf si la déclaration est globale, auquel cas elle est toujours vraie pour les deux formes).

4
geekosaur

UNE)

Object* o;
o = new Object();

`` B)

Object* o = new Object();

Je pense que A et B n'ont aucune différence. Dans les deux cas, o est un pointeur sur la classe Object. La nouvelle instruction Object () crée un objet de classe Object à partir de la mémoire du tas. L'instruction d'affectation attribue l'adresse de la mémoire allouée au pointeur o.

Une chose que je voudrais mentionner que la taille de la mémoire allouée à partir du tas est toujours la taille de (Object) et non sizeof (Object) + sizeof (void *).

2
user966379

Dans vos deux exemples, les variables locales de Object* les types sont alloués sur la pile. Le compilateur est libre de produire le même code à partir des deux extraits s'il n'y a aucun moyen pour votre programme de détecter une différence.

La zone de mémoire pour les variables globales est la même que la zone de mémoire pour les variables statiques - elle n'est ni sur la pile ni sur le tas. Vous pouvez placer des variables dans cette zone en les déclarant static à l'intérieur de la fonction. La conséquence de cela est que l'instance devient partagée entre les appels simultanés de votre fonction, vous devez donc soigneusement considérer la synchronisation lorsque vous utilisez la statique.

Voici n lien pour une discussion sur la disposition de la mémoire d'un programme C en cours d'exécution.

1
dasblinkenlight