La nouvelle syntaxe “ = ” par défaut en C++11
Je ne comprends pas pourquoi ferais-je cela:
struct S {
int a;
S(int aa) : a(aa) {}
S() = default;
};
Pourquoi ne pas simplement dire:
S() {} //instead of S() = default;
pourquoi ramener une nouvelle syntaxe pour que?
- Pinailler:
default
n'est pas un nouveau mot-clé, c'est simplement une nouvelle utilisation d'un mot clé réservé. - double
- Mey être Cette question pourrait vous aider.
- En plus des autres réponses, j'avais aussi valoir que l' '= par défaut;' est plus de l'auto-documentation.
Vous devez vous connecter pour publier un commentaire.
Un défaut constructeur par défaut est expressément défini comme étant le même que définis par l'utilisateur dans le constructeur par défaut sans liste d'initialisation et un vide instruction composée.
Cependant, alors que les deux constructeurs se comportera de la même, de fournir un vide de mise en œuvre ne touchent que certaines propriétés de la classe. Donner un utilisateur défini par le constructeur, même si elle ne fait rien, fait pas un globale et aussi de ne pas trivial. Si vous voulez que votre classe soit un agrégat ou un trivial type (ou par transitivité, un type POD), alors vous devez utiliser
= default
.À démontrer:
En outre, de manière explicite à défaut d'un constructeur de faire
constexpr
si le constructeur implicite auraient été et de donner également à la même spécification d'exception que l'implicite constructeur aurait eu. Dans le cas où vous avez donné, de l'implicite constructeur n'aurait pas étéconstexpr
(car il laisserait un membre de données non initialisées) et il aurait aussi un vide spécification d'exception, donc il n'y a pas de différence. Mais oui, dans le cas général, vous pourriez spécifier manuellementconstexpr
et la spécification d'exception pour correspondre à l'implicite du constructeur.À l'aide de
= default
apporte une certaine uniformité, parce qu'il peut également être utilisé avec des copier/déplacer des constructeurs et des destructeurs. Un vide constructeur de copie, par exemple, ne fera pas la même chose qu'un défaut constructeur de copie (qui effectuera des états-sage copie de ses membres). À l'aide de la= default
(ou= delete
) syntaxe uniforme pour chacune de ces fonctions de membre rend votre code plus facile à lire, en indiquant expressément à votre intention.constexpr
constructeur (7.1.5), la implicitement défini dans le constructeur par défaut estconstexpr
."constexpr
si la déclaration implicite serait, (b) il est implicitement considéré comme ayant la même spécification d'exception que si elle avait été déclarée implicitement (15.4), ..." Il ne fait pas de différence dans ce cas précis, mais en généralfoo() = default;
a un léger avantage surfoo() {}
.constexpr
(puisqu'un membre de données est laissée non initialisée) et sa spécification d'exception permet à toutes les exceptions. Je vais faire plus clair.constexpr
(dont vous avez parlé ne devrait pas faire une différence ici):struct S1 { int m; S1() {} S1(int m) : m(m) {} }; struct S2 { int m; S2() = default; S2(int m) : m(m) {} }; constexpr S1 s1 {}; constexpr S2 s2 {};
Seulements1
donne une erreur, pass2
. Dans les deux clang et g++.constexpr
type de variable.n2210 donne quelques raisons:
Voir Règle-de-Trois devient la Règle de Cinq avec C++11?:
= default
en général, plutôt que de raisons pour faire= default
sur un constructeur vs. faire{ }
.{}
était déjà une caractéristique de la langue avant l'introduction de=default
, ces raisons ne implicitement s'appuyer sur la distinction (par exemple, "il n'y a aucun moyen de ressusciter [supprimée par défaut]" implique que{}
est pas équivalent à la valeur par défaut).C'est une question de sémantique dans certains cas. Il n'est pas très évident avec les constructeurs par défaut, mais il devient évident avec d'autres généré par le compilateur des fonctions de membre du.
Pour le constructeur par défaut, il aurait été possible de faire tout constructeur par défaut avec un vide de corps être considéré comme un candidat pour un trivial constructeur, de même que l'utilisation de
=default
. Après tout, l'ancien vide constructeurs par défaut ont été juridique C++.De savoir si ou non le compilateur comprend ce constructeur pour être trivial est pas pertinent dans la plupart des cas en dehors des optimisations (manuel ou le compilateur ceux).
Cependant, cette tentative pour traiter les vide le corps des fonctions comme "par défaut" se décompose entièrement pour d'autres types de fonctions membres. Envisager le constructeur de copie:
Dans le cas ci-dessus, le constructeur de copie écrite avec un vide corps est maintenant mal. Il n'est plus fait de copier quoi que ce soit. C'est un ensemble très différent de la sémantique de la valeur par défaut constructeur de copie de la sémantique. Le comportement souhaité vous oblige à écrire un peu de code:
Même dans ce cas simple, cependant, il devient beaucoup plus un fardeau pour le compilateur de vérifier que le constructeur de copie est identique à celui qu'elle génère elle-même ou pour elle de voir que le constructeur de copie est trivial (équivalent à un
memcpy
, essentiellement). Le compilateur aurait pour vérifier que chaque membre de l'initialiseur d'expression et de s'assurer qu'il est identique à l'expression d'accéder à la source de membre correspondant, et rien d'autre, assurez-vous qu'aucun des membres sont laissés par défaut non trivial de construction, etc. C'est dans une arrière manière de processus le compilateur pourrait utiliser pour vérifier qu'il est propre généré versions de cette fonction est trivial.Considérons alors la copie opérateur d'affectation qui peut être encore plus poilu, en particulier dans les cas trivial. C'est une tonne de chaudière-plaque que vous ne voulez pas avoir à écrire pour de nombreuses classes, mais vous êtes pas obligés de toute façon en C++03:
Qui est un cas simple, mais c'est déjà plus de code que vous souhaitez toujours être forcé à écrire pour un type simple comme
T
(surtout une fois que nous lancions des opérations de déplacement dans le mélange). Nous ne pouvons pas compter sur un corps est vide de sens ", remplissez les paramètres par défaut", parce que le vide, le corps est déjà parfaitement valide et a une signification claire. En fait, si le corps est vide ont été utilisés pour désigner à compléter "par défaut", alors il n'y aurait pas moyen de faire explicitement un no-op constructeur de copie ou similaires.C'est de nouveau une question de cohérence. Le corps est vide signifie "ne rien faire", mais pour des choses comme la copie constructeurs, vous ne voulez vraiment pas "ne rien faire" mais plutôt de "faire toutes les choses que vous auriez normalement faire si pas supprimé." Donc
=default
. C'est nécessaire pour surmonter supprimé généré par le compilateur membre, comme les fonctions de copier/déplacer des constructeurs et des opérateurs d'affectation. Il est il est "évident" pour le faire fonctionner pour le constructeur par défaut ainsi.Il aurait été sympa de faire de constructeur par défaut avec des corps vides et trivial membre/de la base de constructeurs aussi être considérées comme banales, comme ils l'ont été avec
=default
si ce n'est pour faire de vieux code plus optimale dans certains cas, mais la plupart à faible niveau de code en s'appuyant sur trivial constructeurs par défaut pour les optimisations s'appuie également sur trivial copie des constructeurs. Si vous allez avoir à aller et corriger tous vos vieux copier les constructeurs, c'est vraiment pas beaucoup d'un tronçon d'avoir à résoudre tous vos vieux constructeurs par défaut, soit. Il est aussi beaucoup plus clair et plus évident à l'aide d'un explicite=default
pour désigner vos intentions.Il ya quelques autres choses que généré par le compilateur fonctions de membre fera que vous auriez à faire explicitement les changements à l'appui, ainsi. Soutenir
constexpr
pour les constructeurs par défaut est un exemple. C'est juste plus facile mentalement à utiliser=default
que d'avoir à marquer les fonctions avec tous les autres mots-clés spéciales et tels qui sont implicites=default
et qui a été l'un des thèmes de C++11: rendre la langue plus facile. Il a encore beaucoup de verrues et de l'arrière-compat compromis, mais il est clair que c'est un grand pas en avant à partir de C++03 quand il s'agit de la facilité d'utilisation.= default
feraita=0;
et n'était pas! J'ai dû abandonner en faveur de: a(0)
. Je suis toujours confus au sujet de l'utilité de= default
est tho, est-il sur les performances? il va casser quelque part, si je viens pas utiliser= default
? J'ai essayé de lire toutes les réponses ici acheter, je suis nouveau en c++ trucs et je vais avoir beaucoup de mal à le comprendre.a=0
exemple est à cause du comportement de trivial types, qui sont séparé (et connexes) sujet.= default
et continuent d'accorder desa
sera=0
? d'une certaine façon? pensez-vous que je pouvais créer une nouvelle question comme "comment faire pour avoir un constructeur= default
et accorder les champs sont correctement initialisé?", btw j'ai eu le problème dans unstruct
et pas unclass
, et l'application s'exécute correctement, même pas à l'aide de= default
, je peux ajouter un minimum de structure sur cette question si elle est bonne 🙂struct { int a = 0; };
ensuite, Si vous décidez que vous avez besoin d'un constructeur, vous pouvez par défaut, mais notez que le type ne sera pas trivial (qui est très bien).J'ai un exemple qui montrera la différence:
De sortie:
Comme nous pouvons le voir à l'appel pour vider Un() constructeur ne pas initialiser les membres, tandis que B () - t-il.