Considérer:
struct Person
{
int height;
int weight;
int age;
};
int main()
{
Person p { .age = 18 };
}
Le code ci-dessus est légal en C99, mais pas en C ++ 11.
Quel était le c ++ 11 Pourquoi le comité standard a-t-il exclu la prise en charge d'une fonctionnalité aussi pratique?
OVERLAPPED
est un exemple. Etre capable d'écrire={.Offset=12345};
rendrait le code beaucoup plus clair (et probablement moins sujet aux erreurs). Les sockets BSD sont un exemple similaire.main
C99 n'est pas légal. Il devrait lirestruct Person p = { .age = 18 };
Réponses:
C ++ a des constructeurs. S'il est judicieux d'initialiser un seul membre, cela peut être exprimé dans le programme en implémentant un constructeur approprié. C'est le genre d'abstraction que le C ++ favorise.
D'autre part, la fonctionnalité d'initialisation désignée consiste davantage à exposer et à rendre les membres faciles d'accès directement dans le code client. Cela conduit à des choses comme avoir une personne de 18 ans (ans?) Mais avec une taille et un poids de zéro.
En d'autres termes, les initialiseurs désignés prennent en charge un style de programmation dans lequel les éléments internes sont exposés, et le client a la possibilité de décider comment il souhaite utiliser le type.
C ++ est plus intéressé à mettre la flexibilité du côté du concepteur d'un type à la place, afin que les concepteurs puissent faciliter l'utilisation correcte d'un type et difficile à utiliser de manière incorrecte. Mettre le concepteur en contrôle sur la façon dont un type peut être initialisé en fait partie: le concepteur détermine les constructeurs, les initialiseurs en classe, etc.
la source
Person
laquelle son auteur voulait offrir le plus de flexibilité possible aux utilisateurs pour définir et initialiser les membres? L'utilisateur peut également déjà écrirePerson p = { 0, 0, 18 };
(et pour de bonnes raisons).Person
a un design très C donc les fonctionnalités C peuvent avoir un sens. Cependant, C ++ permet probablement une meilleure conception qui évite également le besoin d'initialiseurs désignés. - À mon avis, la suppression de la restriction sur les initialiseurs en classe pour les agrégats est beaucoup plus conforme à la philosophie de C ++ que les initialiseurs désignés.Le 15 juillet 17, P0329R4 a été accepté dans lec ++ 20standard: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0329r4.pdf
Cela apporte un support limité pourc99Initialiseurs désignés de. Cette limitation est décrite comme suit par C.1.7 [diff.decl] .4, étant donné:
Les initialisations désignées suivantes, valides en C, sont limitées en C ++:
struct A a = { .y = 1, .x = 2 }
n'est pas valide en C ++ car les désignateurs doivent apparaître dans l'ordre de déclaration des données membresint arr[3] = { [1] = 5 }
n'est pas valide en C ++ car l'initialisation désignée par tableau n'est pas prise en chargestruct B b = {.a.x = 0}
n'est pas valide en C ++ car les désignateurs ne peuvent pas être imbriquésstruct A c = {.x = 1, 2}
n'est pas valide en C ++ car tous ou aucun des membres de données doivent être initialisés par des désignateursPour c ++ 17et plus tôt Boost prend en charge les initiateurs désignés et il y a eu de nombreuses propositions pour ajouter un support auc ++standard, par exemple: n4172 et la proposition de Daryle Walker pour ajouter une désignation aux initialiseurs . Les propositions citent la mise en œuvre dec99Les initialiseurs désignés de Visual C ++, gcc et Clang revendiquent:
Mais le comité des normes rejette à plusieurs reprises de telles propositions , déclarant:
Les commentaires de Ben Voigt m'ont aidé à voir les problèmes insurmontables de cette approche; donné:
Dans quel ordre ces fonctions seraient-elles appelées c99:
struct X foo = {.a = (char)f(), .b = g(), .c = h()}
? Étonnamment, dansc99:(Visual C ++, gcc et Clang semblent avoir un comportement convenu car ils effectueront tous les appels dans cet ordre :)
h()
f()
g()
Mais la nature indéterminée de la norme signifie que si ces fonctions avaient une interaction, l'état du programme résultant serait également indéterminé, et le compilateur ne vous avertirait pas : y a-t-il un moyen d'être averti du mauvais comportement des initialiseurs désignés?c ++ n'ont des exigences strictes de liste d'initialiseur 11.6.4 [dcl.init.list] 4:
Alors c ++ le support aurait exigé que cela soit exécuté dans l'ordre:
f()
g()
h()
Rupture de la compatibilité avec les précédents c99implémentations.
Comme indiqué ci-dessus, ce problème a été contourné par les limitations sur les initialiseurs désignés acceptés dansc ++ 20. Ils fournissent un comportement standardisé, garantissant l'ordre d'exécution des initialiseurs désignés.
la source
struct X { int c; char a; float b; }; X x = { .a = f(), .b = g(), .c = h() };
l'appel àh()
est effectué avant l'unf()
ou l' autreg()
. Si la définition destruct X
n'est pas proche, cela va être très surprenant. N'oubliez pas que les expressions d'initialisation ne doivent pas nécessairement être exemptes d'effets secondaires.Un peu de piratage, donc juste partager pour le plaisir.
Et utilisez-le comme:
qui s'étend à:
la source
$
de typeT
, et vous affectez ses membres directement avant de le renvoyer. Nifty. Je me demande s'il y a des problèmes de performance avec cela.Les initialiseurs désignés sont actuellement inclus dans le corpus de travail de C ++ 20: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0329r4.pdf afin que nous puissions enfin les voir!
la source
&
opérateur renverrait l'adresse que l'objet aura pendant sa durée de vie).Deux fonctionnalités principales du C99 qui C ++ 11 mentionnent «les initialiseurs désignés et C ++».
Je pense que le «initialiseur désigné» est lié à l'optimisation potentielle. Ici, j'utilise «gcc / g ++» 5.1 comme exemple.
Nous savions qu'au moment de la compilation,
a_point.x
c'est zéro, donc nous pouvions nous attendre à ce qu'ilfoo
soit optimisé en un seulprintf
.foo
est optimisé pour imprimerx == 0
uniquement.Pour la version C ++,
Et ceci est la sortie du code d'assemblage optimisé.
Nous pouvons voir que ce
a_point
n'est pas vraiment une valeur constante de temps de compilation.la source
constexpr point(int _x,int _y):x(_x),y(_y){}
. L'optimiseur de clang ++ semble également éliminer la comparaison dans votre code. Donc, ce n'est qu'un problème de QoI.struct addrinfo
oustruct sockaddr_in
, il vous reste donc des affectations distinctes des déclarations.