Question

Comment les objets sont-ils stockés en mémoire en C ++?

Pour une classe régulière telle que

class Object
    {
public:
    int i1;
    int i2;
    char i3;
    int i4;
private:
    };

L'utilisation d'un pointeur d'objet en tant que tableau peut être utilisée pour accéder à i1 comme suit?

((Object*)&myObject)[0] === i1?

D'autres questions sur SO semblent suggérer que le fait de transformer une structure en pointeur pointera vers le premier membre pour les types POD. En quoi est-ce différent pour les classes avec constructeurs? De plus, en quoi est-ce différent pour les types non-POD?

Modifier:

En mémoire, la classe ci-dessus serait-elle donc agencée comme suit?

[i1 - 4bytes][i2 - 4bytes][i3 - 1byte][padding - 3bytes][i4 - 4bytes]
Était-ce utile?

La solution

Presque. Vous créez un objet * et vous omettez de prendre une adresse. Reprenons la question comme suit:

((int*)&myObject)[0] == i1

Vous devez être très prudent avec de telles hypothèses. Lorsque vous avez défini la structure, cela devrait être vrai pour tous les compilateurs que vous rencontrerez probablement. Mais toutes sortes d'autres propriétés de l'objet (que vous avez peut-être omises de votre exemple) vont, comme d'autres l'ont dit, le rendre non-POD et pourraient (éventuellement d'une manière dépendante du compilateur) rendre la déclaration ci-dessus fausse.

Notez que je ne serais pas si prompt à vous dire que cela fonctionnerait si vous aviez posé des questions sur i3 - dans ce cas, même pour un POD simple, l'alignement ou l'endianité pourraient facilement vous gâcher.

Dans tous les cas, vous devriez éviter ce genre de chose, si possible. Même si cela fonctionne bien maintenant, si vous (ou toute autre personne qui ne comprend pas que vous faites cette astuce) changez jamais l'ordre de la structure ou ajoutez de nouveaux champs, cette astuce échouera à tous les endroits où vous l'avez utilisée, qui peut être difficile à trouver.

Répondez à votre modification: s’il s’agit de la définition de votre classe et que vous utilisez l’un des principaux compilateurs avec des options par défaut et que vous utilisez un processeur x86, alors oui, vous avez probablement déjà deviné la bonne disposition de la mémoire. Mais le choix du compilateur, les options du compilateur et une architecture de processeur différente pourraient facilement invalider vos hypothèses.

Autres conseils

Les classes sans membres virtuels et sans héritage sont disposées en mémoire, tout comme les structures. Cependant, lorsque vous commencez à avoir des niveaux d'héritage, les choses peuvent devenir difficiles et il peut être difficile de déterminer l'ordre dans lequel les choses sont en mémoire (en particulier l'héritage multiple).

Lorsque vous avez des membres virtuels, ils ont un " vtable " en mémoire qui contient des pointeurs sur la fonction réelle créée en fonction de la hiérarchie d'héritage de la classe.

Le résultat final est le suivant: n’accédez pas aux classes de cette façon si vous pouvez les éviter (et ne les memset pas ou ne les mémorisez pas). Si vous devez faire cela (pourquoi?), Assurez-vous de savoir exactement comment vos objets de classe vont être en mémoire et évitez tout héritage.

La différence est que cette astuce n’est valable que pour les types de POD. C'est vraiment tout ce qu'il y a à faire. La norme spécifie que cette conversion est valide pour un type de POD, mais ne donne aucune garantie sur ce qui se passe avec les types de non-POD.

Cela dépend vraiment du compilateur, ou plutôt, il appartient au compilateur de déterminer la structure de la mémoire.

Par exemple, une combinaison de variables de membres publiques, privées et protégées peut être définie de sorte que chaque type d'accès soit contigu. Ou bien, les classes dérivées peuvent avoir des variables membres entrelacées avec de l’espace inutilisé dans la super classe.

Les problèmes s'aggravent avec l'héritage virtuel: les classes de base pratiquement héritées peuvent être disposées n'importe où dans la mémoire allouée à cette instance particulière.

POD est différent car il doit être compatible avec C.

Généralement, l’important n'est pas de savoir si la classe a un constructeur, mais de savoir si la classe a des méthodes virtuelles. Pour plus de détails, recherchez "vtable" et "vptr" sur Google.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top