56 votes

Sont les "structures anonymes" standard? Et vraiment, qu'est-ce qu'elles sont?

MSDN estime que les structures anonymes ne sont pas standard en C++ :

Une extension C de Microsoft vous permet de déclarer une variable de structure à l'intérieur d'une autre structure sans lui donner de nom. Ces structures imbriquées sont appelées structures anonymes. C++ ne permet pas les structures anonymes.

Vous pouvez accéder aux membres d'une structure anonyme comme s'ils étaient membres de la structure conteneuse.

@K-ballo est d'accord..

On m'a dit que cette fonctionnalité n'est pas nécessairement la même que de simplement créer une structure non nommée mais je ne vois pas de distinction en termes de libellé standard.

C++11 dit:

[C++11: 9/1]: [..] Un class-specifier dont le class-head omet le class-head-name définit une classe sans nom.

et fournit une construction grammaticale entière pour une définition de type sans nom.

C++03 ne contient pas ce libellé explicite, mais indique de manière similaire que l'identifiant dans une définition de type est optionnel, et fait référence à des "classes sans nom" dans 9.4.2/5 et 3.5/4.

  • Donc, MSDN a-t-il tort, et toutes ces choses sont-elles complètement standard?
  • Ou y a-t-il une subtilité que je ne comprends pas entre "structures/classes sans nom" et les mêmes lorsqu'ils sont utilisés comme membres qui les empêche d'être couverts par cette fonctionnalité de C++03/C++11?
  • Est-ce que je ne vois pas de différence fondamentale entre "structure sans nom" et "structure anonyme"? Ils me semblent synonymes.

58voto

Lightness Races in Orbit Points 122793

Tout le texte standard fait référence à la création d'une "struct non nommée" :

struct {
   int hi;
   int bye;
};

Juste un joli type amical, sans nom accessible.

De manière standard, il pourrait être instancié comme un membre comme ceci :

struct Foo {
   struct {
      int hi;
      int bye;
   } bar;
};

int main()
{
   Foo f;
   f.bar.hi = 3;
}

Mais une "struct anonyme" est subtilement différente - c'est la combinaison d'une "struct non nommée" et du fait que vous obtenez magiquement des membres de celui-ci dans l'objet parent :

struct Foo{
   struct{
      int hi;
      int bye;
   }; // <--- pas de nom de membre !
};

int main()
{
   Foo f;
   f.hi = 3;
}

Contrairement à l'intuition†, cela ne crée pas simplement une struct non nommée qui est imbriquée dans Foo, mais vous donne également automatiquement un "membre anonyme" de sorte que les membres soient accessibles dans l'objet parent.

C'est cette fonctionnalité qui n'est pas standard. GCC le supporte, tout comme Visual C++. Les en-têtes de l'API Windows utilisent cette fonctionnalité par défaut, mais vous pouvez spécifier que vous ne le voulez pas en ajoutant #define NONAMELESSUNION avant d'inclure les fichiers d'en-tête Windows.

Comparez avec la fonctionnalité standard des "unions anonymes" qui font une chose similaire :

struct Foo{
   union{
      int hi;
      int bye;
   }; // <--- pas de nom de membre !
};

int main()
{
   Foo f;
   f.hi = 3;
}

† Il semble que, bien que le terme "non nommée" fasse référence au type (c'est-à-dire "la classe" ou "la struct") lui-même, le terme "anonyme" se réfère plutôt au membre réel instancié (utilisant un ancien sens de "la struct" qui se rapproche de "un objet d'un type structuré quelconque"). C'était probablement à la racine de votre confusion initiale.

13voto

Pete Becker Points 27371

Les choses que Microsoft appelle des structures anonymes ne sont pas standard. Une structure sans nom est simplement une structure ordinaire qui n'a pas de nom. Il n'y a pas grand-chose que vous puissiez faire avec une, à moins que vous ne définissiez également un objet de ce type :

struct {
    int i;
    double d;
} my_object;

my_object.d = 2.3;

Les unions anonymes font partie de la norme et ont le comportement que vous attendriez en lisant la description de Microsoft de leurs structures anonymes :

union {
    int i;
    double d;
};

d = 2.3;

9voto

K-ballo Points 44794

La norme parle des unions anonymes : [9.5]/5

Une union de la forme

union { member-specification } ;

est appelée une union anonyme ; elle définit un objet sans nom d'un type non nommé. La member-specification d'une union anonyme ne doit définir que des membres de données non statiques. [ Remarque : Les types et fonctions imbriqués ne peuvent pas être déclarés dans une union anonyme. —note de fin ] Les noms des membres d'une union anonyme doivent être distincts des noms de toute autre entité dans la portée dans laquelle l'union anonyme est déclarée. Aux fins de la recherche de nom, après la définition de l'union anonyme, les membres de l'union anonyme sont considérés comme ayant été définis dans la portée dans laquelle l'union anonyme est déclarée. [ Exemple :

void f() {
    union { int a; const char* p; };
    a = 1;
    p = "Jennifer";
}

Ici, a et p sont utilisés comme des variables ordinaires (non membre), mais étant donné qu'ils sont des membres de l'union, ils ont la même adresse. —exemple de fin ]

Les structs anonymes dont parle Microsoft correspondent à cette fonctionnalité pour les unions mais appliquée aux structs. Ce n'est pas juste une définition sans nom, il est important de noter que les membres de l'union/struct anonyme sont considérés comme ayant été définis dans la portée dans laquelle l'union/struct anonyme est déclarée.

A ma connaissance, il n'y a pas de comportement similaire pour les structs non nommés dans la norme. Notez comment dans l'exemple cité, vous pouvez réaliser des choses qui ne seraient pas autrement possibles, comme partager de la mémoire pour des variables dans la pile, tandis que les structs anonymes n'apportent rien de nouveau.

0voto

Stephane Rolland Points 8110

En C+03, j'ai vu quelqu'un utiliser une structure anonyme pour définir une fonction à l'intérieur d'une fonction de manière plus ou moins similaire à ce que nous pouvons maintenant faire en C++11 avec les lambdas (plus facilement et clairement). J'essaie de retrouver son message mais pour le moment je ne le trouve pas. Je cherche toujours.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X