Confusion concernant l'omission des accolades externes dans les listes d'initialisation pour les agrégats et les structures POD
Dans le domaine de la programmation C, une question courante se pose concernant le utilisation d'accolades dans les listes d'initialisation. Plus précisément, les programmeurs peuvent rencontrer des scénarios dans lesquels des accolades externes semblent être requises pour certains types d'agrégats mais pas pour d'autres. Cet article vise à approfondir le sujet et à fournir des éclaircissements sur les cas où les accolades externes peuvent être omises.
Le problème
Lors de la compilation du code suivant dans Visual C 2010, un message d'erreur est généré :
struct A { int foo; double bar; }; std::array<A, 2> a1 = // error C2078: too many initializers { {0, 0.1}, {2, 3.4} }; // OK std::array<double, 2> a2 = {0.1, 2.3};
L'erreur indique qu'il y a trop d'initialiseurs pour a1, suggérant que les accolades supplémentaires sont nécessaires. Cependant, l’omission des accolades extérieures pour a2 n’entraîne pas d’erreur. Cet écart soulève la question de savoir pourquoi les accolades externes sont nécessaires pour a1 mais pas pour a2.
L'explication
La clé pour comprendre la raison derrière cette différence réside dans le nature de std::array. std::array est classé comme un agrégat et un Plain Old Datatype (POD), contrairement aux autres conteneurs de bibliothèque standard. Contrairement aux conteneurs avec des constructeurs définis par l'utilisateur, std::array n'en a pas. Son premier membre de données est un tableau de taille N, spécifié comme argument de modèle. Ce membre de données est directement initialisé à l’aide d’une liste d’initialisation. Les accolades supplémentaires sont nécessaires car elles entourent le tableau interne en cours d'initialisation.
Pour illustrer davantage ce concept, considérons un type d'agrégat personnalisé Aarray, défini comme suit :
// Custom aggregate with no user-defined constructor struct Aarray { A data[2]; // An internal array };
Initialisation de ceci La structure nécessite l'utilisation d'accolades pour désigner le début et la fin du tableau interne en cours d'initialisation :
Aarray a1 = { { // Begins initialization of the internal array { // Initializes the first element of the internal array 0, 0.1 }, // Ends initialization of the first element {2, 3.4} // Initializes the second element of the internal array } // Ends initialization of the internal array }; // ERROR: Too many initializers if not using braces Aarray b1 = { 0, 0.1, 2, 3.4 };
Le cas de Double
Dans le cas de std::array
std::array<double, 2> a2 = {0.1, 2.3};
Clarification sur l'utilisation des accolades
La norme C fournit des lignes directrices concernant l'utilisation d'accolades dans les listes d'initialisation. La section §8.5.1/11 de la spécification C 11 indique que si la liste d'initialisation commence par une accolade gauche, alors chaque liste suivante de clauses d'initialisation séparées par des virgules initialise les membres d'un sous-agrégat. D'un autre côté, si la liste d'initialisation d'un sous-agrégat ne commence pas par une accolade gauche, alors seulement suffisamment de clauses d'initialisation seront prises pour initialiser les membres du sous-agrégat, toutes les clauses d'initialisation restantes initialisant le membre d'agrégat suivant.
Conclusion
L'utilisation d'accolades externes dans les listes d'initialisation est cruciale pour les agrégats et les structures POD, telles que std::array, car ces types n'ont pas de constructeurs définis par l'utilisateur et le tableau interne est directement initialisé. En revanche, pour les types primitifs, les accolades externes peuvent être omises car les valeurs primitives sont directement initialisées dans l'agrégat. En comprenant la différence entre ces cas, les programmeurs peuvent garantir une initialisation correcte et éviter les erreurs du compilateur.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!