Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
2506 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  initialisation de structure

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

initialisation de structure

n°2114331
GrosBocdel
Posté le 01-12-2011 à 18:56:01  profilanswer
 

Bonjour
Comment initialiser en c++ tous les champs d'une classe à zéro à la construction ou après (sans le faire explicitement sur les 1000000 variables), les pointeurs à NULL et les vector à aucun élément?
 
J'avais une structure c conventionnelle, je faisais un memset à zéro et tout se passait bien.
J'ai rajouté un std::vector dedans et je prends un segfault pour une raison que j'ignore...  :??:  
 
merki

mood
Publicité
Posté le 01-12-2011 à 18:56:01  profilanswer
 

n°2114341
Mara's dad
Yes I can !
Posté le 01-12-2011 à 20:20:04  profilanswer
 

J'ai pas l'explication complète mais il me semble que c'est un peu comme si tu faisait :
 

Code :
  1. int a;
  2. &a = 0;


 
Mais bon, on va attendre un explication plus éclairée.


---------------
Laissez l'Etat dans les toilettes où vous l'avez trouvé.
n°2114353
gilou
Modérateur
Modzilla
Posté le 01-12-2011 à 21:38:43  profilanswer
 

En C, un struct est juste une zone mémoire qui contient des données (et des zones de padding en cas d'alignement).
En C++, un struct, c'est simplement une classe dont les données ont un accés public par défaut (alors qu'il est privé pour une classe).
On peut très bien faire de l'héritage de struct en C++:
struct A { };
struct B : A { };
struct C : B { };
Donc comme c'est une classe, faire un memset à 0 est pas du tout une bonne idée.
Si tu veux initialiser les champs d'un struct à 0, il faut faire comme tu ferais pour une classe.
A+,


Message édité par gilou le 01-12-2011 à 21:40:54

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2114355
GrosBocdel
Posté le 01-12-2011 à 21:42:08  profilanswer
 

explicitement membre par membre?  :sweat:

n°2114357
gilou
Modérateur
Modzilla
Posté le 01-12-2011 à 21:46:02  profilanswer
 

Exactement comme pour une classe.
Mais bon, est il normal qu'une classe ait des centaines de membres (non dérivés)...
 
Donc c'est la qu'il est bon de faire la distinction entre
MaStruct s; // pas d'initialisation
MaStruct s = {}; // initialisation à 0 des membres
En supposant que tu n'as pas défini de constructeur pour ton struct, ce que ton commentaire me laisse supposer.
 
De toute façon, un memset à 0 d'un struct, même en C, c'est pas une bonne idée.
Si certains membres sont des doubles , il n'est pas certain que tous les bits à 0 corresponde à la valeur 0.0 (c'est le cas s'ils sont à la norme IEEE754  néanmoins)
A+,


Message édité par gilou le 01-12-2011 à 21:59:32

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2114358
GrosBocdel
Posté le 01-12-2011 à 21:59:25  profilanswer
 

Je suis obligé d'avoir plein de membres, c'est une structure qui contient toutes les informations d'une journée... Et si je n'écris rien dans le champs il faut qu'il soit à une valeur certaine...
 
 
j'ai trouvé ça qui peut être sympa, mais ça va encore faire deux fois plus de code...
 
 
struct MY_STRUCT
{
    int n1;
    int n2;
};
 
class CMyStruct : public MY_STRUCT
{
public:
    CMyStruct():MY_STRUCT() { }
};
 
 
Initialiser tout à la main c'est horrible

n°2114359
jesus_chri​st
votre nouveau dieu
Posté le 01-12-2011 à 22:00:36  profilanswer
 

un membre de type std::vector<...> sera automatiquement initialisé à 0 élément par le compilo, pas besoin de le faire toi-même.
 
En C, les structures sont des aggrégat d'octets, libre à toi de tout mettre à zero.
En C++ une classe doit être inialisée par son constructeur (et lui seul) ainsi que ses classes de base et ses membre. Remplir à la main avec des zero à coup de memset c'est pas compatible avec le C++, ça c'est pour le C pur.
Le compilateur initialise par défaut tout avec leur constructeur par defaut. Et le constructeur par défaut d'un std::vector<...>, c'est vector à 0 élément.
 

Code :
  1. struct T
  2. {
  3.    std::vector< int > v;
  4. };
  5. T t;
  6. t.v.size() == 0 // vrai

n°2114360
gilou
Modérateur
Modzilla
Posté le 01-12-2011 à 22:00:42  profilanswer
 

Euh, GrosBocdel, si ton struct n'a pas de constructeur, je t'ai donné la solution en une ligne dans mon post, hein...
 
struct MyStruct  
{  
    int n1;  
    int n2;  
};  
 
MyStruct s = {}; // initialise s.n1 et s.n2 à 0
 
A+,


Message édité par gilou le 01-12-2011 à 22:03:47

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2114362
jesus_chri​st
votre nouveau dieu
Posté le 01-12-2011 à 22:02:08  profilanswer
 

ta solution qui consiste à dériver d'une structure pur C (une P.O.D. pour les connaisseur) je la trouve très élégante.
 
Et c'est mieux que d'initialiser chaque membre à la main dans le constructeur.
edit pour gilou : appeler explicitement le constructeur d'une POD revient à faire un ={} donc sa solution est plutôt bien.


Message édité par jesus_christ le 01-12-2011 à 22:03:14
n°2114363
GrosBocdel
Posté le 01-12-2011 à 22:05:03  profilanswer
 

gilou: oui. En fait j'ai une structure de base qui vient du C et sur laquelle j'ai rajouté des std::vector.
Il problème venait de là, à la base.

mood
Publicité
Posté le 01-12-2011 à 22:05:03  profilanswer
 

n°2114364
gilou
Modérateur
Modzilla
Posté le 01-12-2011 à 22:06:29  profilanswer
 

jesus_christ, parce que ça lui permet d'avoir un constructeur qui fait implicitement tout le boulot? oui en effet.
A+,


Message édité par gilou le 01-12-2011 à 22:06:57

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2114366
GrosBocdel
Posté le 01-12-2011 à 22:14:00  profilanswer
 

Pourquoi tous les bits à zéro ça ferait pas zéro sur un float?
Sur une archi particulière?

n°2114368
jesus_chri​st
votre nouveau dieu
Posté le 01-12-2011 à 22:31:14  profilanswer
 

sur une possible archi très très exotique.
Sur tout CPU un peu moderne et pas trop bizarre le zéro est exprimé avec que des 0 bit-à-bit. Le standard IEEE-754 (la norme des flottants) le dit, mais le standard C ne le garantit pas.
 
donc gilou a raison, le memset(.., 0) c'est un mauvais style et c'est pas portable. Le ={} ou le constructeur à la C++ c'est mieux.
 

Code :
  1. struct T { ... only C-like members... };
  2. T t = {}; // bien
  3. T t = T(); // bien aussi
  4. T t; memset( &t, 0, sizeof t ); // pas bien

n°2114369
gilou
Modérateur
Modzilla
Posté le 01-12-2011 à 22:35:13  profilanswer
 

GrosBocdel a écrit :

Pourquoi tous les bits à zéro ça ferait pas zéro sur un float?
Sur une archi particulière?

Les floats, il y a eu tout un tas d'implémentations selon les bécanes. Les normalisations IEEE, c'est relativement récents. Et apparement, il y a eu le cas ou tous les bits à 0 ne signifiait pas 0 (ou en tout cas, c'est un mythe assez tenace).
A+,


Message édité par gilou le 01-12-2011 à 22:36:42

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2114393
GrosBocdel
Posté le 02-12-2011 à 08:43:07  profilanswer
 

et donc si mes structures sont allouées dynamiquement, je suis foutu? initialisation explicite?
 

n°2114404
jesus_chri​st
votre nouveau dieu
Posté le 02-12-2011 à 09:57:23  profilanswer
 

pourquoi foutu ?
Le truc du ={} ou le constructeur C++ ça marche très bien et ça met tout à zero, portable.
Sinon tu peux toujours mettre les membres à zero à la main. C'est juste moins joli.
 

Code :
  1. struct T { float value; };
  2. T t;
  3. t.value = 0;

n°2114425
GrosBocdel
Posté le 02-12-2011 à 11:54:04  profilanswer
 

oui mais avec T *t=new T;
?
 
J'ai des stuctures qui sont des aggrégats d'autres structures, je m'arrache les cheveux.
Faut vraiment que tout soit à zéro car j'ai des champs que je ne sais pas remplir (je n'ai pas leur signification, les structures ne viennent pas de moi) mais que je sauvegarde quand même!


Message édité par GrosBocdel le 02-12-2011 à 11:54:20
n°2114436
Xavier_OM
Monarchiste régicide (fr quoi)
Posté le 02-12-2011 à 12:19:51  profilanswer
 

Je rate un truc ou ça ne marche pas cette histoire de constructeur c++ appelant celui de la struct ?
 

$ cat class_struct.cpp
 
#include <iostream>
using namespace std;
 
struct MyStruct {
    int n1;
    int n2;
};
 
class CMyStruct : public MyStruct {
    public:
        CMyStruct() : MyStruct() {  
            cout << "built!" << endl;
        }
};
 
int main() {
    CMyStruct toto;
    cout << toto.n1 << endl;
    cout << toto.n2 << endl;
    return 0;
}


 

$ g++ -Wall class_struct.cpp -o toto
$ ./toto.exe  
built!
2674688
1629774854


 


---------------
Il y a autant d'atomes d'oxygène dans une molécule d'eau que d'étoiles dans le système solaire.
n°2114463
GrosBocdel
Posté le 02-12-2011 à 13:41:21  profilanswer
 

le code n'était pas de moi, mais ici j'ai bien:
built!
0
0

n°2114470
gilou
Modérateur
Modzilla
Posté le 02-12-2011 à 14:27:40  profilanswer
 

Avec le compilo c++ de Digital Mars
built!
1310640
4332693
 [:chacal_one333]  
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2114486
GrosBocdel
Posté le 02-12-2011 à 14:52:09  profilanswer
 

ok, je me rends, j'initialise à la main

n°2114494
gilou
Modérateur
Modzilla
Posté le 02-12-2011 à 15:09:35  profilanswer
 

Euh non, je viens de voir que le compilo de digital mars accepte pas ceci:
 

Code :
  1. #include <iostream>
  2. using namespace std;
  3. struct MyStruct {
  4.     int n1;
  5.     int n2;
  6. };
  7. int main() {
  8.     MyStruct toto = {};
  9.     cout << toto.n1 << endl;
  10.     cout << toto.n2 << endl;
  11.     return 0;
  12. }


 
qui passe très bien avec mingw (je viens de tester), donc c'est peut être un problème du compilo de Digital Mars.
Noter que le code précédent donne ici 0, 0
tandis qu'avec mingw, l'encapsulation dans une classe donne
built!
4246592
2147348480
 :pt1cable:  
A+,
 
 


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2114496
Un Program​meur
Posté le 02-12-2011 à 15:15:35  profilanswer
 

Xavier_OM a écrit :

Je rate un truc ou ça ne marche pas cette histoire de constructeur c++ appelant celui de la struct ?
 

$ g++ -Wall class_struct.cpp -o toto
$ ./toto.exe  
built!
2674688
1629774854


 


 
Bug apparemment fixe avec gcc 4.4 (il est present ici avec gcc 4.3, pas avec gcc 4.4).
 
Ca ne m'etonnerait pas que sur ce point il y ait eu des problemes d'interpretations pour savoir quand il fallait initialise et quand on pouvait laisser non initialise.


---------------
The truth is rarely pure and never simple (Oscar Wilde)
n°2114503
gilou
Modérateur
Modzilla
Posté le 02-12-2011 à 15:42:50  profilanswer
 

Un Programmeur a écrit :


 
Bug apparemment fixe avec gcc 4.4 (il est present ici avec gcc 4.3, pas avec gcc 4.4).
 
Ca ne m'etonnerait pas que sur ce point il y ait eu des problemes d'interpretations pour savoir quand il fallait initialise et quand on pouvait laisser non initialise.

avec la toute dernière version de mingw que je viens d'installer, donc port de gcc 4.6.1
built!
7
2147340288
 :whistle:  
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2114516
Xavier_OM
Monarchiste régicide (fr quoi)
Posté le 02-12-2011 à 16:19:26  profilanswer
 

Je viens de faire comme toi, upgrade de cygwin de  
    gcc version 4.3.4 20090804 (release) 1 (GCC)  
vers
    gcc version 4.5.3 (GCC)  
 
Et maintenant j'ai 0 (comme avec Visual Studio)


---------------
Il y a autant d'atomes d'oxygène dans une molécule d'eau que d'étoiles dans le système solaire.
n°2114544
gilou
Modérateur
Modzilla
Posté le 02-12-2011 à 17:14:46  profilanswer
 

:o J'ai deux versions, et je viens de voir que c'est pas la bonne qui est appelée par défaut. Je vais mettre mon PATH a jour.
 
Avec la bonne version:
 
built!
0
0
 [:hill]  
A+,


Message édité par gilou le 02-12-2011 à 17:40:03

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2114725
jesus_chri​st
votre nouveau dieu
Posté le 04-12-2011 à 10:36:45  profilanswer
 

Le standard dit que ça doit faire 0 0 car MyStruct est une POD. Certains compilos peuvent ne pas respecter ce standard.
 
Ne pas confondre :

Code :
  1. T *t=new T;


avec

Code :
  1. T *t=new T();


 
Dans le 2e cas, si T est une POD, ça remplit de zéro. Pas dans le premier cas.

n°2114727
gilou
Modérateur
Modzilla
Posté le 04-12-2011 à 10:50:32  profilanswer
 

Oui, mais de toute façon, je vois que le compilo de Digital Mars à l'air à la traine, vu ce qu'il n'a pas fait sur un simple struct.
L'auteur se concentre peut être plus sur son langage D, au vu du peu d'évolution des binaires de son compilo C++ depuis 2 ans.
A+,


Message édité par gilou le 04-12-2011 à 10:50:53

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2114737
GrosBocdel
Posté le 04-12-2011 à 12:33:45  profilanswer
 

jesus_christ a écrit :

Le standard dit que ça doit faire 0 0 car MyStruct est une POD. Certains compilos peuvent ne pas respecter ce standard.
 
Ne pas confondre :
 

Code :
  1. T *t=new T;


avec

Code :
  1. T *t=new T();


Dans le 2e cas, si T est une POD, ça remplit de zéro. Pas dans le premier cas.


 
chauds les marrons

n°2114738
GrosBocdel
Posté le 04-12-2011 à 12:56:23  profilanswer
 

Code :
  1. #include <iostream>
  2. using namespace std;
  3. typedef struct {
  4.     int n1;
  5.     int n2;
  6. } MyStruct;
  7. int main()
  8. {
  9.   MyStruct m0;
  10.   MyStruct *ma=new MyStruct;
  11.   MyStruct *mb=new MyStruct();
  12.   std::cout<<"m0="<<m0.n1<<" "<<m0.n2<<std::endl;
  13.   std::cout<<"ma="<<ma->n1<<" "<<ma->n2<<std::endl;
  14.   std::cout<<"mb="<<mb->n1<<" "<<mb->n2<<std::endl;
  15.   delete ma;
  16.   delete mb;
  17.   return 0;
  18. }


 
C'est le hasard alors si les champs de ma sont à zéro?

n°2114815
jesus_chri​st
votre nouveau dieu
Posté le 05-12-2011 à 10:51:09  profilanswer
 

c'est l'implémentation de ton compilo et/ou OS.
Par exemple sous Windows NT+ (2000, xp et plus) un new remplit de zéro, mais pas sous win98. Ça dépend aussi du mode débug/release.
Et cette subtilité n'est même pas toujours bien respectée par les compilos.

n°2114824
GrosBocdel
Posté le 05-12-2011 à 11:04:07  profilanswer
 

Ha voilà où j'avais déjà vu ça.
J'avais du code vc6 qui fonctionnait en débug et crashait en release.
Il y avait des variables non initialisées. En débug il les mettait à zéro et pas en release.
C'est vrai

mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  initialisation de structure

 

Sujets relatifs
probleme structure[résolu] Choix d'une structure pour ajout et recherche rapide
[VBA]: variable static initialisationStructure d'un site
Exercice structure langage cStructure chainée
Structure clé , valeur avec ordre et doublonsconvertir une structure X509 en format DER.
[ C#] Initialisation attributInitialisation d'un tableau à deux dimensions de structure
Plus de sujets relatifs à : initialisation de structure


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR