initialisation de structure - C++ - Programmation
Marsh Posté le 01-12-2011 à 20:20:04
J'ai pas l'explication complète mais il me semble que c'est un peu comme si tu faisait :
Code :
|
Mais bon, on va attendre un explication plus éclairée.
Marsh Posté le 01-12-2011 à 21:38:43
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+,
Marsh Posté le 01-12-2011 à 21:46:02
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+,
Marsh Posté le 01-12-2011 à 21:59:25
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
Marsh Posté le 01-12-2011 à 22:00:36
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 :
|
Marsh Posté le 01-12-2011 à 22:00:42
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+,
Marsh Posté le 01-12-2011 à 22:02:08
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.
Marsh Posté le 01-12-2011 à 22:05:03
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.
Marsh Posté le 01-12-2011 à 22:06:29
jesus_christ, parce que ça lui permet d'avoir un constructeur qui fait implicitement tout le boulot? oui en effet.
A+,
Marsh Posté le 01-12-2011 à 22:14:00
Pourquoi tous les bits à zéro ça ferait pas zéro sur un float?
Sur une archi particulière?
Marsh Posté le 01-12-2011 à 22:31:14
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 :
|
Marsh Posté le 01-12-2011 à 22:35:13
GrosBocdel a écrit : Pourquoi tous les bits à zéro ça ferait pas zéro sur un float? |
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+,
Marsh Posté le 02-12-2011 à 08:43:07
et donc si mes structures sont allouées dynamiquement, je suis foutu? initialisation explicite?
Marsh Posté le 02-12-2011 à 09:57:23
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 :
|
Marsh Posté le 02-12-2011 à 11:54:04
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!
Marsh Posté le 02-12-2011 à 12:19:51
Je rate un truc ou ça ne marche pas cette histoire de constructeur c++ appelant celui de la struct ?
$ cat class_struct.cpp |
$ g++ -Wall class_struct.cpp -o toto |
Marsh Posté le 02-12-2011 à 13:41:21
le code n'était pas de moi, mais ici j'ai bien:
built!
0
0
Marsh Posté le 02-12-2011 à 14:27:40
Avec le compilo c++ de Digital Mars
built!
1310640
4332693
A+,
Marsh Posté le 02-12-2011 à 15:09:35
Euh non, je viens de voir que le compilo de digital mars accepte pas ceci:
Code :
|
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
A+,
Marsh Posté le 02-12-2011 à 15:15:35
Xavier_OM a écrit : Je rate un truc ou ça ne marche pas cette histoire de constructeur c++ appelant celui de la struct ?
|
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.
Marsh Posté le 02-12-2011 à 15:42:50
Un Programmeur a écrit : |
avec la toute dernière version de mingw que je viens d'installer, donc port de gcc 4.6.1
built!
7
2147340288
A+,
Marsh Posté le 02-12-2011 à 16:19:26
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)
Marsh Posté le 02-12-2011 à 17:14:46
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
A+,
Marsh Posté le 04-12-2011 à 10:36:45
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 :
|
avec
Code :
|
Dans le 2e cas, si T est une POD, ça remplit de zéro. Pas dans le premier cas.
Marsh Posté le 04-12-2011 à 10:50:32
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+,
Marsh Posté le 04-12-2011 à 12:33:45
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.
|
chauds les marrons
Marsh Posté le 04-12-2011 à 12:56:23
Code :
|
C'est le hasard alors si les champs de ma sont à zéro?
Marsh Posté le 05-12-2011 à 10:51:09
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.
Marsh Posté le 05-12-2011 à 11:04:07
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
Marsh Posté le 01-12-2011 à 18:56:01
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