2012-08-04 2 views
3

Consultez le code suivant:Comment réinitialiser une union?

struct T { 
    int a; 
    union { 
     struct { 
      int a; 
     } s1; 
     struct { 
      char b[1024]; 
     } s2; 
    }; 
}; 

int main() { 
    T x = T(); 
} 

Depuis un constructeur explicite est appelée, le zéro-initialisation du code ci-dessus se termine-up tous les membres de données dans x.

Mais je voudrais avoir zéro-initialisé même si un explicit n'est pas appelé. Pour ce faire, une idée serait d'initialiser les membres de données dans leur déclaration, ce qui semble aller pour T :: a. Mais comment puis-je initialiser zéro toute la mémoire occupée par l'union en utilisant les mêmes critères?

struct T { 
    int a = 0; 
    union { 
     struct { 
      int a; 
     } s1; 
     struct { 
      char b[1024]; 
     } s2; 
    }; 
}; 

int main() { 
    T x; // I want x to be zero-initialized 
} 
+0

http://stackoverflow.com/questions/1069621/are-members-of-a-c-struct-initialized-to-0-by-default – Joe

+0

ou simplement 'T x = {};' – Mehrdad

Répondre

6

Pour une union sans constructeur par défaut défini par l'utilisateur, l'initialisation valeur est zéro initialisation. Cependant, l'initialisation de zéro d'une union ne peut pas mettre à zéro toute la mémoire, mais seulement le remplissage et le premier membre. Si le premier membre n'est pas le plus grand, vous pourriez avoir un contenu différent de zéro.

Puisque vous savez que s2 est le plus grand, vous pouvez faire un constructeur par défaut zéros il:

struct T 
{ 
    int a; 
    union { 
     int s1a; 
     char s2b[1024]; 
    }; 
    T() : a(), s2b() {} 
}; 

Et maintenant

T x; 

sera remis à zéro.

+0

Merci. De cette façon, T n'est plus un POD, n'est-ce pas? – Martin

+0

@Martin: Non, ce n'est pas le cas. Mais c'est "la disposition standard". –

+0

N'ajoute pas simplement '{}' à struct {char b [1024];} s2 = {}; résoudre mon problème avec union? Dans ce cas, int main() {T x; } appelle tous les initialiseurs par défaut, lorsque l'union est satisfaite, les suivants de la norme s'appliquent: "- si T est un type de classe (éventuellement qualifié cv) (Article 9), le constructeur par défaut de T est appelé (et le l'initialisation est mal formée si T n'a pas de constructeur par défaut accessible) "(voir 8.5.1) – Martin

6

Vous pouvez mettre à zéro en utilisant memset:

memset(&x, 0, sizeof(x)); 
+2

memset? En C++? –

+3

Il n'est pas déraisonnable d'utiliser memset en C++. Je pense qu'il y a un itérateur dans qui peut être utilisé avec std :: fill pour obtenir le même effet, mais memset est plus simple. – celticminstrel

2

Je suggère de mettre en œuvre un constructeur pour T:

struct T { 
    int a; 
    union { 
     struct { 
      int a; 
     } s1; 
     struct { 
      char b[1024]; 
     } s2; 
    }; 
    T() : a(), s2() {} // <- proper initialisation 
}; 

Dans ce cas, je choisi le plus grand membre de votre union car il est transparent. Sinon, vous pouvez créer explicitement le union lui-même.