IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

SL & STL C++ Discussion :

std::fill vs memset pour les structures.


Sujet :

SL & STL C++

  1. #1
    Membre confirmé
    Inscrit en
    Août 2005
    Messages
    136
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 136
    Par défaut std::fill vs memset pour les structures.
    Bonjour,

    Je viens d'apprendre que "memset" dans du code "c++", il faut éviter!
    "std::fill" serait la pour le remplacer.

    j'essaye, mais je bloque a ce niveau:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    typdef struct
    {
       int a;
       char b[125];
       unsigned long c;
    }MaStruct;
    comment dois je ecrire le std::fill?
    pour l'instant, j'ai fait:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    MaStruct Test[5];
    std::fill(Test,Test+5, 1);
    ps: je remplie de 1 car mon déboguer initialise tout à 0...

    Merci d'avance,

  2. #2
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 397
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 397
    Par défaut
    std::fill(), c'est une fonction template: Elle ne fera pas l'équivalent de memset, car ce que fait memset() n'est pas type-safe.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Membre confirmé
    Inscrit en
    Août 2005
    Messages
    136
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 136
    Par défaut
    heuuuu... oui!!!!

    Donc, j'utilise std::fill juste pour les tableaux, les 'vector', etc, mais pas pour les structures?

  4. #4
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 397
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 397
    Par défaut
    Tu peux utiliser fill() pour les structures, mais ça ne marche pas comme ça. fill() prend un objet du bon type en paramètre:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    MaStruct Test[5];
    MaStruct init = {42, "toto", 0x12345678};
    std::fill(Test,Test+5, init);
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  5. #5
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    std::fill n'initialise pas la mémoire, mais les objets.

  6. #6
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Par défaut
    je me permet de renvoyer vers ce billet d'emmanuel deloget:
    http://blog.emmanueldeloget.com/inde...89-c-et-memset
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  7. #7
    Membre confirmé
    Inscrit en
    Août 2005
    Messages
    136
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 136
    Par défaut
    Merci pour ces infos.

    J'avais bien vu le billet d'emmanuel deloget, mais j'ai peut être lu un peu vite!

    donc, si j'ai bien tout compris:
    - memset : initialise la mémoire en direct.
    - std::fill : init les objet ( du std::vector, à nos propres classes!)

    memset à encore de beau jours devant lui dans mon code!
    je garde quand même a l'esprit de ne PAS le faire quand ma structure ne contient pas que des membres POD.

    Merci à tous!

  8. #8
    Membre émérite

    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    717
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 717
    Par défaut
    Citation Envoyé par zenetcalme Voir le message
    memset à encore de beau jours devant lui dans mon code!
    je garde quand même a l'esprit de ne PAS le faire quand ma structure ne contient pas que des membres POD.
    Si tu code en C ça peut être normal que tu utilise memset. En C++ par contre je me pose des questions, c'est une fonction qu'on utilise très rarement, on lui préfère std::fill, les constructeurs, ...
    Le problème à utiliser memset en C++ c'est qu'un POD peut vite devenir non-POD, suite à l'ajout d'un membre std::string par exemple, et là soit tu oublie que tu as fait plein de memset partout et ça donne des bugs difficiles à trouver, soit tu y pense mais et tu es bon pour remplacer tous les memset par autre chose, alors autan ne pas utiliser memset dès le départ.

  9. #9
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    Tu pourras me traiter d'extrémiste si tu le veux, mais, ma philosophie générale est toujours de ne pas utiliser une fonction ou une manière de faire propre au C là où il existe une alternative propre au C++.

    En effet, je ne comprend pas vraiment l'intérêt de se "casser la tête" à utiliser un tableau dynamique de caractères au lieu d'utiliser une std::string, sachant que la classe std::string est bien plus sécurisante à l'emploi, fournit un éventail de fonction qui permet de faire à la limite bien mieux que ce que ne peut permetrre la gestion d'un char*, et permet même, le cas échéant, de récupérer un char*, entre autre parce qu'il faudrait envoyer le contenu vers une application écrite en C ou parce qu'il faudrait le faire transiter sur un réseau...

    De la même manière, il faut se rappeler que le C ne va jamais travailler qu'avec des types POD, qui sont éventuellement des agrégats de type POD (voire des agrégats contenant des pointeurs vers des types POD)...

    Il n'y a donc a priori aucun problème à utiliser memset en C parce que, justement, on ne risque pas d'aller "chatouiller" autre chose que... des données.

    A l'extrême limite, je concevrais également de répondre à Emanuel que, finalement, l'operator sizeof vient bien à point pour éviter d'aller initialiser quelque chose à quoi l'on n'aurait pas du aller toucher.

    Mais cette remarque n'est valide que dans le cas où l'on parle d'un langage n'utilisant que des types POD...

    En effet, du simple fait que le C++ est orienté objet - et même s'il faut éviter de restreindre la notion d'orienté objet à ce fait - les objets et les types que l'on est amené à manipuler en C++ sont finalement très rarement POD...

    De plus, il est vrai que la S(T)L est suffisemment bien fournie - en classes et en fonctions diverses - et suffisemment "mature" pour nous éviter autant que possible d'avoir à utiliser des tableaux "C style" - quel que puis être le type de donnée manipulé par ce tableau - de manière sécurisante...

    Dés lors, je ne vois finalement aucune raison de préférer quelque chose dont on sait que cela peut amener un tas de problèmes en cas d'inattention ou de modification (parfois finalement très superficielle) à quelque chose dont on a la certitude que le comportement est sécurisé et adapté en toutes circonstances...

    That was my 2 penny's hour
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  10. #10
    Expert confirmé

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Billets dans le blog
    3
    Par défaut
    Sans revenir sur le débat des strings...
    (personnelement, je n'utilise des 'string' que quand je dois *stocker* une chaine ASCII, ce qui est somme toute assez rare, sauf dans de très rares cas d'IO, pour le stockage des chaines j'utilise wstring [la même version unicode], et sinon, dès que ca passe en paramètre, c'est du const wchar_t*, size_t maxlength )

    Il y a une énorme différence entre initiliaser la mémoire et initialiser un objet... Initialiser la mémoire, encore une fois, est rarement utile sauf pour débugger (et en général, en mode debug, nos compilateurs le font pour nous avec une valeur qui n'est pas 0).
    Je n'arrive d'ailleurs même plus à trouver un cas ou initialiser la mémoire soit vraiment utile...

  11. #11
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par nicroman Voir le message
    Sans revenir sur le débat des strings...
    (personnelement, je n'utilise des 'string' que quand je dois *stocker* une chaine ASCII, ce qui est somme toute assez rare, sauf dans de très rares cas d'IO, pour le stockage des chaines j'utilise wstring [la même version unicode], et sinon, dès que ca passe en paramètre, c'est du const wchar_t*, size_t maxlength )
    Je ne suis qu'en partie d'accord avec toi...

    Non pas sur le fait de préférer wstring à string - car l'unicode a effectivement ses avantages - mais sur l'utilisation de la classe (w)string...

    Si je conçois pleinement que l'on renvoie un (w)char* en retour de fonction, pour la raison bien connue qui veut que les différents compilateurs peuvent gérer les (w)string de manière différente, et donc, pour assurer un minimum de compatibilité lorsque l'on travaille sur une dll, je préférerais fortement utiliser la (w)string, tant en passage de paramètre (une référence (constante) sur une (w)string) que pour l'usage local...

    En effet, le passage d'un (w)char* à la place d'une référence sur (w)string est parfaitement autorisé, et, dés le moment où la fonction est compilée - que ce soit dans le cadre d'une bibliothèque statique ou dynamique, ou même dans le cadre d'une application "finale" - le problème ne se pose plus vraiment: au sein d'une dll, seul le retour de fonction peut poser problème en cas de divergence de point de vue de compilateur, et, les bibliothèques statiques sont de toutes manières compilées... pour un compilateur particulier

    Dés lors, je ne vois absolument pas l'intérêt de s'empêtrer dans la gestion (toujours fastudieuse) d'un (w)char* au sein même des fonctions
    Il y a une énorme différence entre initiliaser la mémoire et initialiser un objet... Initialiser la mémoire, encore une fois, est rarement utile sauf pour débugger (et en général, en mode debug, nos compilateurs le font pour nous avec une valeur qui n'est pas 0).
    Je n'arrive d'ailleurs même plus à trouver un cas ou initialiser la mémoire soit vraiment utile...
    Là dessus, par contre, je suis tout à fait d'accord avec toi
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  12. #12
    Membre confirmé
    Inscrit en
    Août 2005
    Messages
    136
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 136
    Par défaut
    J'ai l'impression d'avoir lancé un vieux trool la...

    sinon, en ce qui concerne l'initialisation de ma structure, peut être qu'un peu plus de détail doit être fournit!

    En effet, je développe une API (DLL) qui sert d'interface entre le PC et du matériel USB entre autre. J'ai une structure imposé qui contient pas mal d'information, ou il n'est pas question d'y mettre des pointeurs, des objets etc.

    Lorsque je crée une structure de ce type, je voudrais être sur à 100% que celle ci contient bien que des 0.
    Dans ce cas la, le memset me paraissait parfaitement convenir, et je trouve que la, std::fill alourdirais mon code, et risquerais de le rendre moins lisible.

    il y a le sizeof qui me permet de ne pas craindre de débordement.

    Enfin, si j'en arrive à vouloir initialiser certaines variables, le compilateur y est pour beaucoup... J'ai de plus en plus de mal a lui faire confiance!

    maintenant, je suis bien d'accord avec ce qui a été dit plus haut! quand je fais du c++, j'ai de moins en moins de type purement POD... et le std::fill sera de plus en plus utilisé!

  13. #13
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Si je comprends bien, tu envoies la mémoire de tes objets.
    Le bon truc pas portable...

  14. #14
    Membre confirmé
    Inscrit en
    Août 2005
    Messages
    136
    Détails du profil
    Informations forums :
    Inscription : Août 2005
    Messages : 136
    Par défaut
    L'api est imposée par une norme...
    Je doit renvoyer un pointeur sur une structure!

    moi je vais tout faire pour pas risquer de problème, mais la norme, c la norme!
    franchement, si les gens qui pondais ce genre de truc codait, ça se serais depuis longtemps!

    de plus, je me poserais pas tant de question!!!

  15. #15
    Membre éprouvé
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 537
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 537
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    std::vector<MaStruct> v;
    v.reserve(5); //Non nécéssaire mais va éviter les réallocs.
    MaStruct init = {42, "toto", 0x12345678};
    std::fill_n(v.begin(),5, init);
    return &v[0];
    Et youpiya, on renvoie un beau pointeur.

  16. #16
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 397
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 397
    Par défaut
    Et hop, on renvoie un beau pointeur vers un truc qui aura été désalloué par le destructeur de v...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  17. #17
    Membre éprouvé
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 537
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 537
    Par défaut
    Oui, tu as raison, c'était a prendre comme un pseudo code. Ce que je voulais mettre en avant c'était l'utilisation de &v[0] et non la gestion de la mémoire.

    Mais effectivement, il convient de ne pas renvoyer des pointeur vers des objets dans la pile, ou des composantes de ces objets.

  18. #18
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Salut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    std::vector<MaStruct> v;
    v.reserve(5); //Non nécéssaire mais va éviter les réallocs.
    MaStruct init = {42, "toto", 0x12345678};
    std::fill_n(v.begin(),5, init);
    tu initialise un tableau de taille 0 ??
    Y as de forte chance que tu te prenne une exception ou un beau plantage si tu n est plus grand que ton reserve.

    tu peut faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    std::vector<MaStruct> v(5);//tableau de taille 5
    MaStruct init = {42, "toto", 0x12345678};
    std::fill(v.begin(),v.end(), init);
    soit

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    std::vector<MaStruct> v;//tableau de taille 5
    v.reserve(5);//si tu veut
    MaStruct init = {42, "toto", 0x12345678};
    std::fill_n(std::back_inserter (v), 5, 11);

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. surchage d'opérateur pour les structures
    Par Flow_75 dans le forum C++
    Réponses: 5
    Dernier message: 22/01/2009, 11h08
  2. Besoin d'aide pour les structures de données dynamiques
    Par aurelie689 dans le forum Pascal
    Réponses: 3
    Dernier message: 26/12/2007, 21h29
  3. aide pour exercice sur les structures
    Par demetria dans le forum C
    Réponses: 10
    Dernier message: 25/09/2007, 22h11
  4. Alignement mémoire pour les structures.
    Par SpaceToto dans le forum Visual C++
    Réponses: 4
    Dernier message: 14/09/2006, 11h15
  5. [débutant] equivalent à sprintf pour les std::string
    Par Biosox dans le forum SL & STL
    Réponses: 22
    Dernier message: 26/08/2005, 12h46

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo