8
votes

Dans quel cas il n'y a pas de constructeur du tout, même un constructeur par défaut?

dans Ce livre je suis en train de lire, je suis actuellement dirigé sur ceci:

Une classe n'a pas besoin d'un constructeur. Un constructeur par défaut n'est pas nécessaire si l'objet n'a pas besoin d'initialisation.

suis-je correct en déduire de ce qui précède que le compilateur ne génère pas de constructeur par défaut pour la classe / la structure dans certains cas? Si oui, quels sont ces cas? Je serai aventurer et dire que POD est probablement un. Y a-t-il d'autres?

edit: J'ai changé le titre car le titre original a donné le sens que j'ai demandé quand un constructeur par défaut n'est pas défini au lieu de demander quand une classe ne dispose pas d'un constructeur.


2 commentaires

Notez que "Constructeur par défaut" n'est pas un synonyme de "constructeur généré par compilateur".


Un constructeur par défaut est toujours généré, mais il n'est pas toujours appelé. Considérez une variable locale qui n'est pas Const, est de type de pod et est déclarée sans initialisateur. L'objet est pavé de la mémoire. Même si le constructeur par défaut existe, il n'est pas appelé à construire l'objet. Les membres de données ont une valeur indéterminée.


9 Réponses :


3
votes

Si vous créez toujours des objets d'une classe à l'aide d'un constructeur avec des paramètres, il n'aurai pas besoin du constructeur par défaut.

Le compilateur génère un constructeur par défaut pour chaque classe, mais si vous définissez votre propre constructeur pour cette classe, le compilateur ne génère pas de constructeur par défaut. Tant que vous créez des objets d'une telle classe à travers le constructeur que vous avez fourni, la classe n'aura pas besoin et dispose d'un constructeur par défaut. xxx

dans le contexte de l'exemple ci-dessus, Considérez la citation du livre:

Une classe n'a pas besoin d'un constructeur. Un constructeur par défaut n'est pas nécessaire si l'objet n'a pas besoin d'initialisation.

Dans l'exemple ci-dessus tant que l'objet de myClass est créé à l'aide de n ° 1, la classe ne nécessite pas et dispose d'un constructeur par défaut.

Le constructeur par défaut doit être défini pour la classe, si l'objet de myClass est créé de manière à ce qui nécessite le constructeur par défaut, c'est-à-dire: # 2. < / p>


2 commentaires

Mon titre aurait dû être "dans quels cas il n'y a pas de constructeur du tout, même un constructeur par défaut"


@Samaursa: La seule fois, il n'y a pas de constructeur de quelque sorte que vous ayez déclaré un constructeur mais que vous n'avez pas fourni de mise en œuvre. Le résultat est une classe inutilisable. Si, d'autre part, vous ne déclarez aucun constructeur, le compilateur sera (DOIT!) Créer un constructeur par défaut en votre nom. C'est ce qui se passe avec une classe de pod. Dans le cas d'une classe de POD, ce constructeur généré automatiquement n'est pas appelé dans certaines circonstances. Voir ma réponse pour plus de détails.



5
votes

Un constructeur par défaut est toujours déclaré. Mais ce n'est pas toujours défini. Seulement s'il est utilisé, alors le compilateur (ou vous) le définissez. Exemples: xxx

Notez que cela a des conséquences pratiques directes xxx


16 commentaires

Donc, dès que vous instaniez l'objet, un constructeur est défini et appelé? Qu'en est-il des structures pure C? Si j'ai typlef struct a {int a; } A; , puis tapant A A; ne génère pas de constructeur le fait (je pensais que c'était la définition d'une structure de pod)? Pourquoi est-ce différent dans l'exemple ci-dessus? Est-ce simplement parce que nous traitons maintenant avec C ++?


Le compilateur génère toujours un constructeur par défaut pour une classe de pod. Cela ne l'utilise pas toujours.


@Davidhammen: Que voulez-vous dire par "Génération"? Un constructeur par défaut n'est déclaré implicitement déclaré que si une classe n'a pas de constructeurs déclarés par l'utilisateur et qu'il n'est défini que s'il est utilisé.


@CHARDLES: Les seuls objets qui ne sont pas initialisés via un constructeur sont des objets de pod. La présence d'un constructeur déclaré par l'utilisateur signifie que la classe n'est pas pod. Le compilateur déclare toujours implicitement un constructeur par défaut lorsque la classe est définie. Si le compilateur définit que le constructeur par défaut à cette époque est à la mise en œuvre. Dans tous les cas, vous manquez le point ici, qui est incorporé dans les mots si l'objet n'a pas besoin d'initialisation . Les objets non-POD sont toujours initialisés.


@Davidhammen: La première phrase de votre commentaire n'est pas vraie. Certains objets de type de classe non pod peuvent également être initialisés par un constructeur. Par exemple, une classe sans aucun constructeur déclaré par l'utilisateur peut être initialisé de la valeur, même s'il ne s'agit pas de classes de POD et d'agrégats peut être initialisé avec une clause d'initialisateur BRACE SLLOFER qui n'utilise pas non plus un constructeur, même si la classe d'agrégat est non-Pod. . De plus, les implémentations ne sont pas autorisées à définir un constructeur par défaut déclaré implicitement déclaré, sauf s'il est utilisé qui se produira pour des objets initialisés par défaut de type de classe non-Pod.


@Samaursa théoriquement, en C ++ 03, il ne génère pas de constructeur pour votre A A; , car il n'appelle pas de constructeur en premier lieu. Mais en C ++ 0x, il génère un constructeur et l'appelle. Le résultat final est cependant le même. La spécification en C ++ 0X est plus simple et présente moins de cas spéciaux. En tant qu'utilisateur, vous ne remarquerez pas la différence, cependant.


@Johanes: le contexte du texte cité est un livre sur l'optimisation. L'initialisation de contournement est l'une des astuces que certaines personnes utilisent pour raser les cycles de processeur. Il n'y a aucune raison de vous embêter avec l'initialisation si le code suivant définira ultérieurement tous les éléments du contenu de l'objet en question et des éléments non définis ne sont pas accessibles dans l'intervalle.


@David Je ne sais pas pourquoi tu me dis ça. Il ne semble pas être une réponse ou un commentaire à un commentaire que j'ai fait ou à la réponse que j'ai faite. Pouvez-vous s'il vous plaît élaborer?


@Johannes: Elaboration: votre réponse n'est pas une réponse à la question de l'OP. L'OP n'était pas très clair en ce qui concerne le contexte, mais le livre électronique lié est très clair. La phrase "Un constructeur par défaut n'est pas nécessaire si l'objet n'a pas besoin d'initialisation" est effectué en ce qui concerne l'optimisation. L'objectif est d'éviter d'appeler tout constructeur. Certains constructeurs seront appelés si vous déclarez tout constructeur pour une classe, puis déclarez une variable de cette classe. La plupart des réponses ont été sur ce qui se passe si vous déclarez un constructeur. La bonne réponse dans ce contexte ne doit pas déclarer un constructeur.


@David Hammen: En ce qui concerne C ++, un livre électronique aléatoire n'utilise pas la norme ISO C ++. Et un livre qui ne parvient pas à faire la distinction entre les déclarations et les définitions devrait être considéré comme moins autoritaire.


Vous manquez le point. L'auteur de ce livre électronique profite de la manière dont C ++ 03 fonctionne. Aucun constructeur ne sera appelé à une instanciation d'une classe de POD non globale, non-const, est déclarée sans une liste d'initialistes. Il y a une pénalité de performance dans l'initialisation d'un objet. Éviter que la pénalité de performance est un piratage (petit) d'optimisation. J'ai tendance à aller à l'autre extrême: déclarez toujours un constructeur et assurez-vous toujours que chaque membre est initialisé. Je n'aime pas les données non initialisées qui courent autour de mes programmes.


@Msalters: Je suis d'accord avec votre point en ce qui concerne C ++, un livre électronique aléatoire n'attrume pas la norme ISO C ++ . Ma question a déclenché de la notion de pod. Depuis que C n'a pas la notion de ctors / dtors (d'où des solutions de contournement comme Stackoverflow.com/questions/537244/constructor-in-c/... ) J'ai deviné que, dans C ++ une structure, une pod ne recevrait pas de CTOR / DTOR, car il est coûteux (même s'il s'agit d'un coût mineur - J'ai déjà lu le temps et le temps, en C / C ++, vous ne payez pas pour ce que vous n'utilisez pas [par exemple des pointeurs non inités à NULL automatiquement]) et d'où la question.


@Samaursa: avec des compilateurs modernes, le coût est littéralement zéro . Pas une seule instruction n'est ajoutée à votre code.


@Msalters: Ne pas dire que je ne vous croyez pas, mais une preuve de la sauvegarde serait géniale! Et juste parce qu'un compilateur fait tout pour moi ne signifie pas que je ne devrais pas le savoir du tout. Je suis curieux et oui, il est lié à l'optimisation, mais cela ne signifie pas que je ne devrais pas automatiquement savoir à ce sujet car compilateurs sont si bons .


@Samaursa: essentiellement, le CTOR par défaut est en ligne et ne touche pas les membres. En conséquence, zéro instructions sont inlinées. La preuve est facile: vérifiez simplement la sortie de votre compilateur préféré.


@Msalters: Assez juste, je vais essayer cela à la première chance possible. BTW, je suppose que cela ne soit inliné que lorsque des optimisations sont activées, corrigez-vous? Potentiellement, vous pouvez raser le temps (aussi petit) de la construction de débogage, oui?



0
votes

À mon avis, cette phrase signifie que vous n'avez pas toujours à écrire votre propre constructeur par défaut, car certaines classes n'ont pas besoin d'être initialisées par défaut.

Par exemple, si votre classe contient plusieurs champs de classe qui fournissent leur propre constructeur par défaut, vous n'avez pas besoin d'écrire un constructeur par défaut, car le constructeur des membres est appelé de toute façon par défaut.

à l'extrême opposé, vous voudrez peut-être écrire un struct ou un de la classe de PODS pour laquelle vous comptez sur le programmeur pour initialiser correctement ses champs manuellement; Dans ce cas, vous ne pouvez pas écrire un constructeur par défaut, le compilateur écrira donc son propre qui quittera ces champs à leurs valeurs non initialisées par défaut (en réalité, ce sera un non-op et sera probablement optimisé).


0 commentaires

8
votes

Une classe n'a pas besoin d'un constructeur. Un constructeur par défaut n'est pas nécessaire si l'objet n'a pas besoin d'initialisation.

Je pense que l'auteur parle de cette situation: xxx

Dans certaines circonstances, un constructeur ne sera pas appelé, période. Dès que vous écrivez un constructeur, vous n'avez pas de classe de pod, le constructeur sera donc appelé.

s'il s'agit d'une bonne ou d'une mauvaise chose d'avoir un objet courir qui contient aléatoire, ininitialisé Les données sont une question différente entièrement.


3 commentaires

Hmm, c'est exactement ce que je demandais. Pourriez-vous confirmer ce que vous avez dit "Dans certaines circonstances, un constructeur ne sera pas appelé, période" par une citation (la norme ou peut-être démontable). Je vais alors marquer cela comme la réponse à la place (+1)


Et juste pour vous assurer que j'ai bien compris ... Le pod_type Vous pouvez être utilisé peut être utilisé (en appelant pod_type.somevar ), mais ses membres ne sont pas initialisés car il n'y a pas de Fonctions membres (constructeurs ou autres) ... correct?


@Samaursa: ISO / CEI 14882: 2003 (E) Section 8.5 Paragraphe 9 (Saisie de la mine): "Si aucun initialiseur n'est spécifié pour un objet, et l'objet est de type de classe non numérisée (ou une matrice qualifiée de CV). Encore), l'objet doit être initialisé par défaut; si l'objet est de type Cons-qualifié, le type de classe sous-jacente doit avoir un constructeur par défaut déclaré par l'utilisateur. Sinon, si aucun initialiseur n'est spécifié pour un objet non statique , l'objet et ses subordonnements, le cas échéant, ont une valeur initiale indéterminée "



0
votes

Le compilateur ne déclare que et définit un constructeur par défaut généré automatiquement si vous n'avez pas fourni de constructeur.

avec un Classe d'origine non instanciable Cependant, il est possible d'empêcher tout type de constructeur de travail. En ajoutant un constructeur factice avec un paramètre factice, il est possible de ne tuer que le constructeur par défaut généré automatiquement, à la charge de plus de rubanches rouges.


0 commentaires

0
votes

Il y a une certaine ambiguïté dans votre question. Vous voyez, les actions implicites que le compilateur prend avec les constructeurs concernent les deux déclarant em> eux et définir em> eux. Si un constructeur est déclaré mais non défini, considérez-vous qu'il existe ou non?

Quoi qu'il en soit, il n'y a aucun moyen de créer une classe qui n'a aucun constructeur déclaré em> pour cela. Le constructeur de copie, pour un exemple, est toujours déclaré. Il n'y a aucun moyen de le supprimer. Si vous ne le déclarez pas vous-même, le compilateur le déclarera pour vous. P>

comme pour le constructeur par défaut - il est possible de supprimer sa déclaration implicite. Si vous déclarez tout em> constructeur vous-même (c'est-à-dire explicitement), le compilateur ne déclarera pas implicitement le par défaut. Mais dans ce cas, votre classe aura bien sûr un constructeur: celui que vous avez déclaré vous-même. (De plus, comme je l'ai dit ci-dessus, le constructeur de copie est toujours déclaré). P>

comme pour les constructeurs em> implicitement définis ... Ils sont définis par le compilateur uniquement si vous les utilisez. Et, bien sûr, ils ne sont définis que si cela est possible. (Si vous utilisez un constructeur implicite et qu'il s'avère impossible de définir, alors votre programme ne compilera pas simplement). P>

Donc, une fois encore, quand il s'agit de déclaré em> Constructeurs, il n'est pas possible d'avoir une classe sans constructeurs du tout. Toute classe a au moins un constructeur déclaré pour celui-ci. P>

Si vous êtes intéressé par constructeurs em> définis spécifiquement, il est en effet possible d'avoir une classe, pour laquelle aucun constructeur n'est défini . Voici un exemple pour vous p>

struct S {
  S(const S&);
};


1 commentaires

La question concerne les classes pour lesquelles no constructeur est invoqué lorsqu'un exemple de cette classe est créé. Le constructeur n'est pas appelé pour les variables non globales et non constituées d'un type de POD déclarée sans une liste d'initialistes. Le contenu initial d'un tel objet est indéterminé. Si vous déclarez un constructeur, vous n'avez plus de classe de pod, votre exemple n'est donc pas ce que l'OP a demandé (et ce n'est certainement pas ce que l'auteur de ce livre électronique liait à l'OP était écrit).



0
votes

Un constructeur par défaut n'est pas défini pour une classe si un autre constructeur est déclaré.

Pour les types de pod (dans le sens d'être à la fois trivial et standard, car ces termes sont définis en C ++ 11), il s'agit d'un point utile si le compilateur génère un constructeur ou non, car les constructeurs générés par le compilateur sont triviaux. Pour les détails de Gory, consultez Qu'est-ce que sont Agrégats et pods et comment / pourquoi sont-ils spéciaux?


0 commentaires

0
votes

alors simplement mettre - (dans le contexte du CPP) Si non constructeur est défini, le compilateur n'a pas de constructeur par défaut. Il est défini par le compilateur uniquement s'il est requis.

Il existe certains cas où il est fait par le compilateur. Dont certains sont - p>

  1. Lorsque nous avons une classe qui a un objet de classe de base en tant que membre (et constructeur de classe dérivé n'est pas défini). Dans ce cas, la rétrécissement par défaut pour la classe dérivée est créée car le prologue de son contrat doit appeler le contruceur de la classe de base. LI>
  2. Nous avons un objet de conteneur. Sous le code explique cela. P>

    class Legs
    {
    ctor(); // ctor stands for constructor
    };
    class cat
    {
    Legs leg;
    public:
    cat(){}
    };
    
  3. En cas de fonctions virtuelles, le réglage du pointeur de table virtuel sur la table V correcte est effectué dans le constructeur. Pour cette raison également, le constructeur par défaut sera défini par le compilateur. P> li> ol> p>


0 commentaires

-1
votes

quelque_type quelque_function () { Pod_type this_is_intenterally_uninitialisé; ... }


0 commentaires