web-dev-qa-db-fra.com

C++: Quelle est la taille d'un objet d'une classe vide?

Je me demandais quelle pouvait être la taille d'un objet d'une classe vide. Cela pourrait sûrement ne pas avoir 0 octet puisqu'il devrait être possible de le référencer et de le pointer comme n'importe quel autre objet. Mais quelle est la taille d'un tel objet?

J'ai utilisé ce petit programme:

#include <iostream>
using namespace std;

class Empty {};

int main()
{
    Empty e;
    cerr << sizeof(e) << endl;
    return 0;
}

Le résultat obtenu sur les compilateurs Visual C++ et Cygwin-g ++ était 1 octet _! C'était un peu surprenant pour moi puisque je m'attendais à ce qu'il soit de la taille de la machine Word (32 bits ou 4 octets).

Quelqu'un peut-il expliquer pourquoi la taille d'un octet? Pourquoi pas 4 octets? Est-ce que cela dépend du compilateur ou de la machine aussi? Aussi, quelqu'un peut-il donner une raison plus convaincante de la raison pour laquelle un objet de classe vide ne le sera pas aura une taille de 0 octet?

96
Ashwin Nanjappa

Citant Style et technique C++ de Bjarne Stroustrup FAQ , la raison pour laquelle la taille est différente de zéro est "Pour que les adresses de deux objets différents soient différentes." Et la taille peut être 1 parce que l'alignement n'a pas d'importance ici, car il n'y a rien à regarder.

115
Sol

La norme indique que sizeof ()> = 1 est présent dans tous les objets dérivés.

Sauf s'il s'agit d'un champ de bits (class.bit), un objet le plus dérivé doit avoir une taille non nulle et occuper un ou plusieurs octets de stockage. Les sous-objets de la classe de base peuvent avoir une taille nulle. ISO/IEC FDIS 14882: 1998 (E) intro.object

29
TrayMan

C'est vraiment un détail de mise en œuvre. Il y a très longtemps, je pensais que cela pourrait être zéro octet ou mille octets, que cela n'a aucune incidence sur la spécification du langage. Mais, après avoir examiné la norme (section 5.3.3), sizeof est défini comme renvoyant toujours un ou plus, quoi qu’il en soit.

La taille d'une classe la plus dérivée doit être supérieure à zéro.

Ceci est nécessaire, entre autres, pour vous permettre de gérer des tableaux d'objets et des pointeurs sur ceux-ci. Si vos éléments étaient autorisés à être de taille zéro, alors &(array[0]) serait identique à &(array[42]), ce qui causerait toutes sortes de dégâts à vos boucles de traitement.

La raison pour laquelle il peut ne pas s'agir d'un mot machine est qu'il ne contient aucun élément nécessitant qu'il soit aligné sur une limite de mot (telle qu'un entier). Par exemple, si vous placez char x; int y; dans la classe, mon compte GCC est cadencé à huit octets (car le deuxième int doit être aligné dans cette implémentation).

12
paxdiablo

Il existe une exception: les tableaux de longueur 0

#include <iostream>

class CompletlyEmpty {
  char NO_DATA[0];
};

int main(int argc, const char** argv) {
  std::cout << sizeof(CompletlyEmpty) << '\n';
}
6
Konstantin Nikitin

Même s'il n'est pas nécessaire d'assigner de la mémoire pour une classe vide, mais pour créer des objets de classes vides, le compilateur affecte la mémoire minimale pouvant être affectée, à savoir 1 octet. De cette façon, le compilateur peut distinguer de manière unique deux objets de la même classe vide et sera en mesure d'affecter l'adresse de l'objet à un pointeur du type de classe vide.

5
lalatendu

Je pense qu'il pourrait être utile de créer un lien vers une réponse expliquant ce bien aussi. Il s'agit de de boost::compressed_pair par Logan Capaldo

Cela peut vous aider: -) http://bytes.com/topic/c/insights/660463-sizeof-empty-class-structure-1-a

La taille d'une classe ou d'une structure vide est 1

Cela s’explique par la mise en œuvre correcte du fichier En standard, l'une des choses mentionnées dans la norme C++ est la suivante: "aucun objet n'aura la même adresse en mémoire que toute autre variable" ... Quoi est le moyen le plus simple de s’assurer de cela? Assurez-vous que tous les types ont un taille non nulle. Pour ce faire, le compilateur ajoute un octet factice aux structures et aux classes qui n'ont ni données membres, ni virtuel fonctions afin qu’ils aient une taille de 1 plutôt que de 0 et ils sont alors assurés d'avoir une adresse mémoire unique.

3
Arsalan Mehmood

la raison pour la classe sans données membres mais ayant un octet de taille 1 est que le * texte fort * doit être stocké en mémoire pour qu'une référence ou un pointeur puisse pointer sur l'objet de cette classe

2
Ramiz

L'allocation d'un octet pour une classe vide dépend du compilateur. Les compilateurs doivent s'assurer que les objets résident dans des emplacements de mémoire différents et allouer une taille de mémoire non nulle à un objet. Écoutez les notes sur ce sujet ici: http://listenvoice.com/listenVoiceNote.aspx?id=27

Même si les compilateurs allouent une taille non nulle à une classe vide, ils optimisent également la création de nouvelles classes à partir de classes vides. Écoutez à propos de l'optimisation de la base vide sur les questions d'entrevue de la programmation c ++ de ListenVoice.

2
user332764

classe vide - cette classe ne contient aucun contenu.

toute classe qui n'est pas vide sera représentée par son contenu en mémoire.

maintenant, comment une classe vide sera représentée en mémoire? en mémoire 1 octet est requis.

0
Ganesh
#include<iostream>
using namespace std;


    class Empty { };
    int main()
    {
        Empty* e1 = new Empty;
        Empty* e2 = new Empty;

        if (e1 == e2)
            cout << "Alas same address of two objects" << endl;
        else
            cout << "Okay it's Fine to have different addresses" << endl;

        return 0;
    }

Sortie: ok c'est bien d'avoir différentes adresses

Le renvoi de la taille 1 garantit que les deux objets n'auront pas la même adresse. 

0
Sandeep_black

Il est différent de garantir que les deux objets auront des adresses différentes ..__ Les différents objets doivent avoir des adresses différentes, de sorte que la taille d'une classe vide est toujours de 1 octet.

0
Yadvendra Yadav

Je pense que cette question n’a qu’un intérêt théorique, mais qu’elle n’a pas d’importance dans la pratique.

Comme d'autres l'ont déjà souligné, le fait de dériver d'une classe vide ne fait pas de mal, car cela ne consommera pas de mémoire supplémentaire pour la portion de classe de base.

De plus, si une classe est vide (ce qui signifie qu’elle - théoriquement - n’a pas besoin de mémoire par instance, c’est-à-dire qu’elle n’a pas de données membres non statiques ni de fonctions membres virtuelles), alors toutes ses fonctions membres peuvent tout aussi bien (et devrait) être défini comme statique. Il n'est donc pas nécessaire de créer une instance de cette classe.

Conclusion: si vous écrivez une classe X vide, rendez toutes les fonctions membres statiques. Vous n'aurez alors plus besoin de créer d'objets X et les classes dérivées ne seront en aucun cas affectées.

0
kidfisto

Je pense que c’est le cas, car 1 octet est la plus petite unité de mémoire utilisable en tant que paramètre fictif et ne peut pas donner une taille nulle, car il ne sera pas possible de créer un tableau d’objets.

et la chose que vous avez dite "C'était un peu surprenant pour moi puisque je m'attendais à ce qu'il soit de la taille de la machine Word (32 bits ou 4 octets)." sera vrai pour la variable de référence (mots macine) de type empty (), pas la taille de la classe elle-même (qui est un type de données abstrait),

0
lazarus