Est-il implicite constructeur par défaut en C++?
Dans le livre que je suis en train de lire en ce moment ( C++ Sans Crainte ), il est dit que si vous ne déclarez pas de constructeur par défaut d'une classe, le compilateur fournit un pour vous, qui "remet à zéro à chaque membre de données". J'ai expérimenté avec cela, et je ne vois aucune réinitialisation de la conduite. Je ne peux pas trouver quelque chose qui le mentionne sur Google. Est-ce juste une erreur ou d'un caprice d'un compilateur spécifique?
- Des sons comme vous avez besoin d'un meilleur livre. 😉
- Yup. Unforgiveable erreur, si les "zéros de chaque mamber" est en effet une citation littérale.
- Je pense que c'est une commune c une idée fausse. Je pensais la même chose jusqu'à ce que j'ai visité cette page. Je suis sûr que je l'ai lu quelque part ou j'ai appris dans une classe.
- Je soupçonne que cette confusion se pose quand les gens apprennent que des objets globaux sont garantis d'être mis à zéro, mais il est vraiment préférable de ne pas compter sur qui que ce soit.
- Je devrais faire un point mineur, que les données sont toujours à zéro dans un programme. Le système d'exploitation n'est présent sur la page de l'allocation. La question est de tous les extras, 'junk' C++ fait, avant même l'exécution de votre programme.
Vous devez vous connecter pour publier un commentaire.
Si vous ne définissez pas un constructeur, le compilateur va définir un constructeur par défaut pour vous.
La mise en œuvre de cette
constructeur par défaut est:
Remarque:
Le POD de données (int,float,pointeur, etc.) n'ont pas explicitement un constructeur, mais l'action par défaut est de ne rien faire (dans la palette de C++ de la philosophie; nous ne voulons pas payer pour quelque chose de moins que nous le demander explicitement).
Si aucun destructeur/Constructeur de copie/opérateur d'Affectation est définie le compilateur crée un de ceux pour vous (si une classe a toujours un destructeur/Constructeur de Copie/Opérateur d'Affectation (à moins que vous tentez de tricher et de déclarer explicitement un, mais ne pas le définir)).
L'implémentation par défaut est:
Destructeur:
Constructeur De Copie:
Opérateur D'Affectation:
Note de la Copie de la Construction/opérateur d'Affectation de la GOUSSE de Données est simplement de copier les données (d'Où le peu de problème de copie associés avec des pointeurs).
int i = int();
conclut aveci == 0
Je pense qu'il est intéressant de remarquer que le constructeur par défaut est créé uniquement par le compilateur si vous fournissez aucun constructeur que ce soit. Cela signifie que si vous ne fournissez un constructeur qui prend un argument, le compilateur va pas créer de la valeur par défaut no-arg constructeur pour vous.
La réinitialisation de comportement de votre livre parle est probablement spécifique à un compilateur. J'ai toujours supposé qu'il peut varier et que vous devez explicitement initialiser les données membres.
Si vous legalistically analyser la langue de l'2003 standard, puis les réponses sont oui, et pas. Cependant, ce n'est pas toute l'histoire car contrairement à un utilisateur défini dans le constructeur par défaut, un implicitement défini dans le constructeur par défaut n'est pas toujours utilisé lors de la création d'un objet à partir de zéro, il y a deux autres scénarios: pas de construction et états-sage de la valeur d'initialisation.
La "construction" est vraiment juste un vice de forme parce qu'il est fonctionnellement différent de l'appel de la trivial constructeur par défaut. L'autre cas est le plus intéressant: les sages de la valeur d'initialisation est appelée à l'aide de "()" [comme si invoquant explicitement un constructeur qui n'a pas d'arguments] et il ignore ce qui est techniquement appelé la constructeur par défaut. Au lieu de cela, il effectue de manière récursive la valeur d'initialisation sur chaque membre de données, et pour les types de données primitifs, finalement, cela se résout à zéro-initialisation.
Donc, en effet, le compilateur fournit deux implicitement par défaut définis par les constructeurs. L'un des qui ne effectuer l'initialisation à zéro de la primitive de données sur les membres et dont l'autre n'a pas. Voici quelques exemples de comment vous pouvez appeler chaque type de constructeur:
et
Remarque: Si un l'utilisateur déclaré constructeur par défaut ne existe pas, alors membre-sage de la valeur d'initialisation simplement les appels et s'arrête.
Ici est un peu la ventilation détaillée de ce que dit la norme à ce sujet...
Si vous ne déclarez pas un constructeur, le compilateur crée implicitement un constructeur par défaut [12.1-5]
Le constructeur par défaut ne pas initialiser les types primitifs [12.1-7]
Si vous initialiser un objet avec les "()", ce n'est pas directement appeler le constructeur par défaut. Au lieu de cela, il incite à une longue séquence de règles appelé valeur d'initialisation [8.5-7]
L'effet net de la valeur d'initialisation est que la déclarées implicitement constructeur par défaut n'est jamais appelé. Au lieu de cela, un membre récursif-sage de la valeur d'initialisation est invoquée pour en fin de compte zéro-initialiser toute primitive membres et appelle le constructeur par défaut sur tous les membres qui ont un utilisateur déclaré constructeur [8.5-5]
Valeur d'initialisation s'applique même pour les types primitifs; ils seront remis à zéro. [8.5-5]
Tout cela est vraiment discutable pour la plupart des besoins. L'écrivain d'une classe ne peut généralement supposer que les membres de données sera mis à zéro lors de l'implicite de la séquence d'initialisation -- de sorte que toute auto-gestion de la classe doit définir son propre constructeur si elle a une primitive de membres de données qui nécessitent une initialisation.
Alors, quand est-ce important?
Il peut y avoir des circonstances où le code générique veut forcer l'initialisation de types inconnus. La valeur d'initialisation fournit un moyen pour ce faire. Rappelez-vous juste que implicites zéro-l'initialisation n'a pas lieu si l'utilisateur a fourni un constructeur.
Par défaut, les données contenues par std::vector est la valeur d'initialisation. Cela peut éviter de mémoire débogueurs de l'identification des erreurs de logique associée par ailleurs à la mémoire non initialisée tampons.
Ensemble des tableaux de primitives de type ou plain-vieux-données" (POD)-type de structures peut être remis à zéro en utilisant la valeur d'initialisation de la syntaxe.
Ce post a plus de détails sur les variations entre les différentes versions de la norme, et il note également un cas où la norme est appliquée différemment dans les principaux compilateurs.
C++ génère un constructeur par défaut, mais seulement si vous n'avez pas fournir l'un de vos propres. La norme ne dit rien à propos de la réinitialisation des données membres. Par défaut, lors de la première de la construction de tout objet, ils sont pas définis.
Cela peut être source de confusion parce que la plupart du C++ types primitifs N'ont par défaut "constructeurs" qui initialisation à zéro (int(), bool(), double(), long(), etc.), mais le compilateur ne fait pas appel à init POD membres comme elle le fait pour les membres de l'objet.
Il est intéressant de noter que le TSL ne l'utilisation de ces constructeurs par défaut-construire le contenu de conteneurs qui détiennent des types primitifs. Vous pouvez prendre un coup d'oeil à cette question pour plus de détails sur la façon dont les choses dans des conteneurs STL obtenir inited.
Le constructeur par défaut créé pour une classe ne sont pas initialiser types intégrés, mais il va appeler le constructeur par défaut sur tous les membres définis par l'utilisateur:
Le compilateur va générer de la valeur par défaut des constructeurs et destructeurs si l'utilisateur créés ne sont pas présents. Ils ne vont PAS modifier l'état de toutes les données membres.
En C++ (et C) le contenu de toutes les données allouées n'est pas garanti. En debug configurations de certaines plates-formes se mettre à une valeur connue (par exemple, 0xFEFEFEFE) pour aider à identifier les bugs, mais cela ne devrait pas être invoqué.
Zéro-ing out se produit uniquement pour les variables globales. Donc, si votre objet est déclaré dans la portée globale, ses membres seront zéro-ed out:
C++ ne pas garantir la mise à zéro de la mémoire. Java et C# n' (dans une façon de parler).
Certains compilateurs peuvent, mais ne dépendent pas que.
En C++11, un constructeur par défaut généré par le compilateur est marqué comme supprimé , si :
http://en.cppreference.com/w/cpp/language/default_constructor
C++ génère un constructeur par défaut. En cas de besoin (déterminé au moment de la compilation, je crois), il permettra également de générer un défaut constructeur de copie et un constructeur par défaut. Je n'ai rien entendu sur les garanties pour la réinitialisation de la mémoire si.
Le compilateur par défaut ne sera pas générer le constructeur par défaut, à moins que la mise en œuvre ne nécessite pas un .
Donc , en gros, le constructeur doit être un non-trivial constructeur.
Pour le constructeur pour être non négligeable constructeur, voici les conditions dans lesquelles chacun peut suffire:
1) La classe a une fonction membre virtuelle.
2) membre de la Classe des sous-objets et les classes de base ont non négligeable des constructeurs.
3) Une classe a la hiérarchie d'héritage virtuel.