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

Langage C++ Discussion :

Ersatz de std::array


Sujet :

Langage C++

  1. #1
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    Billets dans le blog
    1
    Par défaut Ersatz de std::array
    Bonjour,

    Je continue dans la joie et la bonne humeur à découvrir le C++ et je m'attaque un morceau qui me donne bien du fil à détordre. J'espère que vous allez rallumer ma lanterne.

    Codant dans un environnement embarqué contraint, je dois éviter autant que possible l'allocation dynamique. Je trompe peut-être mais cela implique de se passer de std::vector. J'ai souhaité me tourner vers std::array mais hélas je n'ai pas droit à C++11 (oui je cumule...). J'ai donc tenté de coder un ersatz pour avoir un tableau à allocation sans dynamique sur lequel je pourrais avoir quelques méthodes un peu cool. Ma 1ère idée a donc été de faire quelque chose comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    #ifndef ARRAY_H
    #define ARRAY_H
     
    #include <assert.h>
    #include <cstddef>
     
    template<typename __type, std::size_t __size>
    struct array
    {
    public:
        __type& operator[](std::size_t index)
        {
            assert(index >= 0 && index < __size && "Index is out of bounds!");
            return __private_data[index];
        }
     
        std::size_t size()
        {
            return __size;
        }
     
    private:
        __type __private_data[__size];
    };
    Ça commençait bien jusqu'à ce que je souhaite faire ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    array<int, 3> array = { 1, 2, 3 };
    Cela me donnait l'erreur suivante :
    error: could not convert '{1, 2, 3}' from '<brace-enclosed initializer list>' to 'array<int, 3u>'
    En regardant dans l'en-tête fournissant std::array, j'ai remarqué que le champ stockant les données était public, alors j'ai fait pareil et du coup l'erreur disparait.

    Pourquoi ?

    Merci d'avance pour vos réponses !

  2. #2
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    Bonjour,

    Une structure peut être initialisée par son constructeur si au moins un a été défini
    Sinon elle peut être initialisée par une liste correspondant à chacun de ses membre publics
    Ici il n'y a pas de constructeur, donc seule possibilité les membres publics.
    Le membre étant un tableau l'initialisation doit être :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    array<int, 3> array = { { 1, 2, 3 } };
    Curieusement la seconde accolade n'a pas été réclamée.

  3. #3
    Membre Expert
    Avatar de Pyramidev
    Homme Profil pro
    Tech Lead
    Inscrit en
    Avril 2016
    Messages
    1 513
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Tech Lead

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 513
    Par défaut
    Bonjour,

    Citation Envoyé par Bktero Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    array<int, 3> array = { 1, 2, 3 };
    Cela me donnait l'erreur suivante :
    error: could not convert '{1, 2, 3}' from '<brace-enclosed initializer list>' to 'array<int, 3u>'
    En regardant dans l'en-tête fournissant std::array, j'ai remarqué que le champ stockant les données était public, alors j'ai fait pareil et du coup l'erreur disparait.

    Pourquoi ?
    Citation Envoyé par dalfab Voir le message
    Le membre étant un tableau l'initialisation doit être :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    array<int, 3> array = { { 1, 2, 3 } };
    Curieusement la seconde accolade n'a pas été réclamée.
    Voici un lien vers les règles de l'aggregate initialization :
    http://en.cppreference.com/w/cpp/lan...initialization

    • Toutes les variables membres doivent être publiques.
    • Un membre tableau ne nécessite pas forcément de mettre des accolades en plus. Quand on ne met pas d'accolades en plus, on parle de brace elision.


    La raison pour laquelle le langage impose que les membres soient public pour utiliser l'aggregate initialization est que, pour que l'appelant puisse utiliser cette dernière, il a besoin de savoir quels sont les membres de la structure et dans quel ordre.
    L'intérêt des variables membres private, c'est de pouvoir les changer sans changer le code de l'utilisateur.

  4. #4
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    Billets dans le blog
    1
    Par défaut
    Merci les gars !

    J'avais effectivement chercher sur cppreference mais soit je n'avais pas trouvé la bonne page, soit je n'avais pas bien lu...

    Je marque comme résolu mais le C++ n'est pas un langage facile, c'est un sacré morceau pour rentrer dedans pleinement, vous risquez de me revoir

  5. #5
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 152
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 152
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par Bktero Voir le message
    En regardant dans l'en-tête fournissant std::array, j'ai remarqué que le champ stockant les données était public, alors j'ai fait pareil et du coup l'erreur disparait.
    Et le tableau contenait bien les données attendues ?
    Je dirais qu'étant donné que la classe est triviale, ne contient ni méthode virtuelle ni rien d'autre que son champ, un vrai POD, le compilateur a optimisé le tout pour que ça finisse similaire à int tab[3] = {1,2,3};, soit juste l'écriture possible de l'initialisation inline d'un tableau à sa déclaration.
    Mais la bonne façon de faire serait effectivement via l'initializer-list, constructeur et opérateur d'affectation.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  6. #6
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

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

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    Billets dans le blog
    1
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Et le tableau contenait bien les données attendues ?
    Je n'ai pas regardé en debug, j'ai juste regardé le fichier .h

  7. #7
    Membre actif
    Profil pro
    Inscrit en
    Novembre 2010
    Messages
    69
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2010
    Messages : 69
    Par défaut
    Salut,

    Juste une petite note, qui peux t’intéresser.
    La class vector possède une méthode reserve() qui te permet d'initialiser sa taille. Par la suite tu peux tester si sa size() et inférieur a sa capacity() pour ajouter ou non un nouvel élément. Il n'y alors plus d’allocation dynamique. La taille de ton vector étant fixé à son initialisation.

    Par contre, il me semble (à vérifier) que si tu ne fais pas le test (explicité plus haut) entre la capacity() et la size() avant d'ajouter un nouvel élément, il sera ajouté dynamiquement dans le vector. C'est donc au programmeur de verifier le non "débordement" du vector.


    Cordialement,

  8. #8
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 152
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 152
    Billets dans le blog
    4
    Par défaut
    Mais std::vector utilisera toujours la heap, réserve ou pas. L'intérêt d'array c'est d'utiliser la stack, en connaissant par avance (à la compilation) la taille nécessaire
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  9. #9
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Mais std::vector utilisera toujours la heap, réserve ou pas.
    Pas forcément, même si par défaut, tu as raison : Tu peux fournir un allocateur à std::vector, qui va allouer dans une zone prédéfinie sur la stack (ce qui ne marche pas très bien, je crois, c'est qu'il n'y a pas trop moyen pour l'allocateur de dire au vector : Désolé, plus de place...).
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  10. #10
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    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 395
    Par défaut
    Citation Envoyé par JolyLoic Voir le message
    (ce qui ne marche pas très bien, je crois, c'est qu'il n'y a pas trop moyen pour l'allocateur de dire au vector : Désolé, plus de place...).
    Lancer une exception bad_alloc?
    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.

  11. #11
    Membre éprouvé
    Inscrit en
    Mai 2012
    Messages
    65
    Détails du profil
    Informations forums :
    Inscription : Mai 2012
    Messages : 65
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Lancer une exception bad_alloc?
    Citation Envoyé par Bktero
    Codant dans un environnement embarqué contraint
    Pas sur que ce soit un choix très judicieux vu le coup d'une exception lorsqu'elle est levée.

  12. #12
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Dans l'absolu, ce n'est pas lever une exception qui coûte cher, mais l'attraper.

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

Discussions similaires

  1. Réponses: 10
    Dernier message: 15/04/2014, 18h49
  2. Réponses: 2
    Dernier message: 23/05/2013, 18h24
  3. Performances std::array C++ 2011 vs C array
    Par Kaluza dans le forum Langage
    Réponses: 6
    Dernier message: 07/12/2011, 18h15
  4. Question sur la classe std::array
    Par Aleph69 dans le forum C++
    Réponses: 4
    Dernier message: 07/07/2011, 17h49

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