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

C++ Discussion :

Problème de pointeur ?


Sujet :

C++

  1. #1
    Membre habitué
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Mai 2014
    Messages
    227
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2014
    Messages : 227
    Points : 162
    Points
    162
    Par défaut Problème de pointeur ?
    Bonjour tout le monde actuellement j'ai coder plusieurs "outils" pour prochainement la création d'un simple jeu. Là j'en suis à l'étape des input ( Boutons, Champs, Champs multiligne, case, etc... ). Pour éviter d'avoir trop de ressources à charger, j'ai créer un manager qui s'occupe :
    - De charger les textures dans la cg
    - De l'ajouts de différents input tel que les boutons
    - De l’affichage de ceux ci (je leur donne les pointeurs des textures à utiliser)
    - Du test pour savoir si l'on à cliqué dessus
    - Et cetera...
    Pour créer les boutons et autres, je n'ai pas eu de problèmes. Mais depuis que j'utilise le Manager que j'ai créé, j'ai pus me rendre compte que cela ne fonctionne pas très bien.
    En faite je crée trois bouton.
    Les trois s'affiche sans problème mais seul le premier bouton fonctionne, si je clique dessus il change d'état et de textures. Les autres ne réagisse pas du tout !

    Voici le code actuel :

    La classe Button
    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
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
     
    class Button : public sf::Drawable, public sf::Transformable
        {
        public:
     
        Button( std::string name, bs::Vector4f def, sf::Texture *texture ) : b_name{name}, b_array(sf::Quads, 4), b_state{State::DEFAULT}
        {
            b_texture = texture;
     
            b_array[0].position = sf::Vector2f(0,0);
            b_array[1].position = sf::Vector2f(def.a.x,0);
            b_array[2].position = sf::Vector2f(def.a.x,def.a.y);
            b_array[3].position = sf::Vector2f(0,def.a.y);
     
            b_array[0].texCoords = sf::Vector2f(0,0);
            b_array[1].texCoords = sf::Vector2f(def.a.x,0);
            b_array[2].texCoords = sf::Vector2f(def.a.x,def.a.y);
            b_array[3].texCoords = sf::Vector2f(0,def.a.y);
     
            this->setPosition(def.b);
            b_size = def.a;
        }
     
        void setTextureOnPress( sf::Texture *texture )
        {
            b_texturePress = texture;
        }
     
        void setTextureOnHover( sf::Texture *texture )
        {
            b_textureHover = texture;
        }
     
        sf::Vector2f size() const
        {
            return b_size;
        }
     
        bool isTouch( sf::Vector2f pos )
        {
            if( pos.x < this->getPosition().x + size().x && pos.x > this->getPosition().x )
                if( pos.y < this->getPosition().x + size().y && pos.y > this->getPosition().y )
                    return true;
     
            return false;
        }
     
        void press()
        {
            b_state = State::PRESSED;
        }
     
        void release()
        {
            b_state = State::DEFAULT;
        }
     
        bool tried()
        {
            if( b_state == State::PRESSED )
                return true;
            return false;
        }
     
        std::string name() const
        {
            return b_name;
        }
     
        private:
     
        virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const
        {
            states.transform *= getTransform();
            if( b_state == State::HOVER )
                states.texture = b_textureHover;
            else if ( b_state == State::PRESSED )
                states.texture = b_texturePress;
            else
                states.texture = b_texture;
            target.draw(b_array, states);
        }
     
        std::string const b_name;
        sf::Texture *b_texture;
        sf::Texture *b_textureHover;
        sf::Texture *b_texturePress;
        sf::VertexArray b_array;
        State b_state;
        sf::Vector2f b_size;
     
        };
    La classe Manager

    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
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
     
    class Manager : public sf::Drawable, public sf::Transformable
        {
        public:
     
            Manager(){this->load();}
     
            void add( std::string name, ButtonType type, bs::Vector4f shape )
            {
                switch(type)
                {
                case ButtonType::NORMAL:
                    {
                        std::map<ButtonType,sf::Texture>::iterator it;
                        it = m_textures.find(ButtonType::NORMAL);
                        m_buttons.push_back(new Button(name,shape,&it->second));
                    }
     
                    break;
                default:
                    break;
                }
     
            }
     
            std::string trigger( sf::Vector2f pos )
            {
                std::string rsl;
     
                for( size_t i{0}; i < m_buttons.size(); i++ )
                {
                    if( m_buttons[i]->isTouch(pos) )
                    {
                        if( m_buttons[i]->tried() )
                        {
                            m_buttons[i]->release();
                            rsl = m_buttons[i]->name();
                        }
                        else
                        {
                            m_buttons[i]->press();
                        }
                    }
                }
     
                return rsl;
            }
     
        private:
     
        void load()
        {
            sf::Texture t;
            m_textures[ButtonType::NORMAL] = t;
     
            if(!m_textures[ButtonType::NORMAL].loadFromFile("C:/Test/f.png"))
                std::cout << "Erreur";
        }
     
        virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const
        {
            for( size_t i{0}; i < m_buttons.size(); i++ )
            {
                target.draw(*m_buttons[i]);
            }
        }
     
        std::map<ButtonType,sf::Texture> m_textures;
        std::vector<Button*> m_buttons;
     
        };
    Le code qui crée les boutons

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    void load( Loadable l, Input::Manager &manager )
        {
            manager.add("Play", Input::ButtonType::NORMAL, bs::Vector4f(120,30,100,100));
            manager.add("Quit", Input::ButtonType::NORMAL, bs::Vector4f(120,30,100,150));
            manager.add("Options", Input::ButtonType::NORMAL, bs::Vector4f(120,30,100,200));
        }
    bs::Vector4f, ButtonType, State, Loadable

    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
     
    enum Loadable{ MENU, HUD };
     
    enum ButtonType{NORMAL, PLAY, VALID, CANCEL, QUIT, BUY, SELL};
     
    enum State{DEFAULT,PRESSED,HOVER};
     
    struct Vector4f
        {
            Vector4f(){}
            Vector4f( float x, float y, float z, float w)
            {
                sf::Vector2f v(x,y);
                a = v;
                v.x = z; v.y = w;
                b = v;
            }
     
            sf::Vector2f a;
            sf::Vector2f b;
        };
    Un code pour tester l'ensemble

    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
    25
    26
    27
    28
     
    sf::RenderWindow window;
        window.create(sf::VideoMode(640,480), "Test", sf::Style::Default);
     
        Input::Manager *m = new Input::Manager();
        bs::load(Loadable::MENU, *m);
     
        while(window.isOpen())
        {
            sf::Event e;
            while( window.pollEvent(e))
            {
                if( e.type == sf::Event::MouseButtonPressed )
                    if( m->trigger(sf::Vector2f( sf::Mouse::getPosition(window).x, sf::Mouse::getPosition(window).y )  ) != "" )
                    {
                       //st
                    }
                if( e.type == sf::Event::MouseButtonReleased )
                    if( m->trigger(sf::Vector2f( sf::Mouse::getPosition(window).x, sf::Mouse::getPosition(window).y )  ) != "" )
                    {
                       //st
                    }
            }
     
            window.clear(sf::Color(230,230,230));
            window.draw(*m);
            window.display();
        }
    Merci de votre aide, je suis un peu perplexe pour le coup x)

    Ps: Pour le moment le code n'est pas du tout "sécurisé" mais j'aimerais déjà qu'il fonctionne avant de plus m'avancer

  2. #2
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 113
    Points : 32 958
    Points
    32 958
    Billets dans le blog
    4
    Par défaut
    if( pos.y < this->getPosition().x + size().y && pos.y > this->getPosition().y ) ?
    les passages de paramètre en copie à tout va
    une conception qui a l'air un peu étrange
    un manager drawable et transformable ça sonne faux
    une const-correctness pas toujours respectée
    une allocation dynamique inutile de Inputs::Manager dans le main
    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.

  3. #3
    Membre habitué
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Mai 2014
    Messages
    227
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2014
    Messages : 227
    Points : 162
    Points
    162
    Par défaut
    Citation Envoyé par Bousk Voir le message
    if( pos.y < this->getPosition().x + size().y && pos.y > this->getPosition().y ) ?
    les passages de paramètre en copie à tout va
    une conception qui a l'air un peu étrange
    un manager drawable et transformable ça sonne faux
    une const-correctness pas toujours respectée
    une allocation dynamique inutile de Inputs::Manager dans le main
    Pour les paramètres en copie à chaque fois je ne sais pas si c'est réellement utile de faire une const& donc soit je ne fait que des copies et on me dit que c'est inutile, soit j'en fait pas et on me dit que ça ne vas pas non plus x)
    Le manager drawable ne vas pas le rester longtemps, c'est complètement illogique donc je ferais une méthode draw() ?
    Pour l'alloc dynamique en soit ce n'est pas faux, c'est juste inutile pour le moment mais je ne ferais pas non plus Inuput::manager manager car je veux en faire un singleton une fois mes problèmes et le code corrigé
    Je précise aussi que je n'ai jamais fait ce genre de chose donc mon code change littéralement à chaque fois que je remarque/apprend que je fait mal certaine choses.
    Pour ce qui en est le la const-correctness et bien comme dit rien n'est sécurisé, j'ai vu pas mal d'endroit où ça n'allait pas du tout mais pour le moment je me penche sur le fonctionnement ( cela dit ce n'est peut-être pas la meilleur méthode, j'en conçoit )
    Er merci pour l'erreur que j'avais pas vu, donc ça fonctionne mais c'est pas propre comme code x) Je vais le corrigé et reposté le code corrigé pour savoir si il y à encore des problème de conception, des erreurs...

    Peut-tu m'expliquer comment savoir quand il faut faire ou ne pas faire une copie ? ( Normalement je ne fait jamais de copie car je trouve que rien ne doit être copié, sauf qu'on ma fait pas mal de réflexion par rapport à ça, que le gain été trop minime pour être nécessaire... )

  4. #4
    Expert éminent
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 562
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    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 562
    Points : 7 628
    Points
    7 628
    Par défaut
    Citation Envoyé par Disixlis Voir le message
    Peut-tu m'expliquer comment savoir quand il faut faire ou ne pas faire une copie ? ( Normalement je ne fait jamais de copie car je trouve que rien ne doit être copié, sauf qu'on ma fait pas mal de réflexion par rapport à ça, que le gain été trop minime pour être nécessaire... )
    En effet, en général on doit éviter de faire une copie et préférer les passages par référence constante. Cette règle est suffisante pour respecter un code sérieux et optimum. En peaufinant on peut trouver des exceptions.
    int f( char x ) semble préférable à int f( char const& x ) car un char est petit (mais avec un processeur type ARM en mode ARM, pourrait mieux optimiser le second!)
    Curieusement Objet operator+( Objet o1 , Objet const& o2 ) est souvent mieux que Objet operator+( Objet const& o1 , Objet const& o2 ), avec un paramètre copié et l'autre passé par référence! Si on écrit le code des fonctions dans les 2 cas, on en voit la raison
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    Complexe operator+(Complexe c1, Complexe const& c2) noexcept {
       // il y a eu copie du 1er, ou bien optimisation du passage par RVO 
       c1.real += c2.real;  // on modifie le premier objet
       c1.imag+= c2.imag;
       return c1; // retour par RVO, copie ou move (NRVO rarement)
    }
    Complexe operator+(Complexe const& c1, Complexe const& c2) {
       Complexe x; // nécessité de créer un objet + ou - gros
       x.real = c1.real + c2.real;
       y.imag = c1.imag + c2.imag;
       return x; // retour par NRVO, RVO, copie ou move
    }
    Le second code est statistiquement moins optimal.
    On peut trouver d'autres exemples discutables.

  5. #5
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 113
    Points : 32 958
    Points
    32 958
    Billets dans le blog
    4
    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
    Membre éprouvé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Points : 937
    Points
    937
    Par défaut
    J'appuie la réponse de dalfab

    En général (sauf pour les types primitifs), les paramètres sont passés par référence constante.

    Cependant, lorsque dans la fonction ou méthode appelée, si on effectue de toutes façons une copie de paramètre, alors il se peut qu'il soit optimal de faire un passage par valeur.
    Faire une recherche sur "copy and swap idiom"; ici par exemple
    http://stackoverflow.com/questions/3...and-swap-idiom
    il est proposé une bonne explication avec un exemple détaillé.

  7. #7
    Membre confirmé

    Inscrit en
    Août 2007
    Messages
    300
    Détails du profil
    Informations forums :
    Inscription : Août 2007
    Messages : 300
    Points : 527
    Points
    527
    Par défaut
    @dalfab, camboui: Le sujet de passer par copie ou par référence constante a des ramifications au delà de la comparaison du cout de la copie d'un objet par rapport au cout de la copie d'un pointeur.
    En effet, dans un cadre multi tache, le compilateur peut faire des optimisations s'il a une copie locale qu'il ne peut pas faire en cas de passage d'un pointeur. Ce débat a été popularisé en 2009 par un gourou du C++ (Dave Abrahams, liens morts, googler "want speed? pass by value").
    D'autres gourous tout aussi respectables ont des opinions beaucoup plus nuancées (Alexandrescu).
    Les arguments des deux bords font appel à l'intelligence d'un compilateur hypothétique, soit disant capable dans l'avenir de décider de mettre une référence même s'il y a une valeur en argument si la copie est lourde en mono-thread, et inversement. Bien des années plus tard, je ne connais pas de compilateur qui fasse cela. Il parait qu'il y a des langages qui résolvent le problème en forçant les copies (Haskell? - si quelqu'un en sait plus que moi sur le sujet, contribution bienvenue ). Il n'est donc pas "évident" de baser la décision sur le cout de copie, puisque les concepteurs de ce langage ont décidé de ne pas tenir compte de cet aspect (et non, ils ne sont pas cons, même s'ils décident en toute connaissance de cause d'aller à rebours des autres). Cela peut aller même plus loin: certains dispositifs informatiques tout à fait respectables (GPU!) ne peuvent même pas proposer, quel que serait le langage de programmation, certains types de références.

    Si les experts s'écharpent encore sur le sujet, c'est peut-être un poil trop stratosphérique pour nous autres mortels lecteurs de forum...
    Je recommande humblement tout de même de se poser la question lors du passage en argument dune donnée utilisée un peu partout, même lourde. Un conseil que je donne aux arrivants dans notre société est de se demander avant de faire une ref const "est-ce un pointeur vers de la ROM?". N'oublions pas que l'aspect sémantique de la "constness" en C++ est incomplet ou flou: il mélange l'interdiction de modifier avec la garantie que cela ne bougera pas.

    Là encore, d'autres langages font la distinction, et donc apportent des réponses bien plus faciles et claires à ce souci un peu trop spécifique à C++ (mais aussi toute la famille C/Pascal et compagnie).
    "Maybe C++0x will inspire people to write tutorials emphasizing simple use, rather than just papers showing off cleverness." - Bjarne Stroustrup
    "Modern C++11 is not your daddy’s C++" - Herb Sutter

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 611
    Points
    30 611
    Par défaut
    Citation Envoyé par ac_wingless Voir le message
    @dalfab, camboui: Le sujet de passer par copie ou par référence constante a des ramifications au delà de la comparaison du cout de la copie d'un objet par rapport au cout de la copie d'un pointeur.
    En effet, dans un cadre multi tache, le compilateur peut faire des optimisations s'il a une copie locale qu'il ne peut pas faire en cas de passage d'un pointeur. Ce débat a été popularisé en 2009 par un gourou du C++ (Dave Abrahams, liens morts, googler "want speed? pass by value").
    D'autres gourous tout aussi respectables ont des opinions beaucoup plus nuancées (Alexandrescu).
    Les arguments des deux bords font appel à l'intelligence d'un compilateur hypothétique, soit disant capable dans l'avenir de décider de mettre une référence même s'il y a une valeur en argument si la copie est lourde en mono-thread, et inversement. Bien des années plus tard, je ne connais pas de compilateur qui fasse cela. Il parait qu'il y a des langages qui résolvent le problème en forçant les copies (Haskell? - si quelqu'un en sait plus que moi sur le sujet, contribution bienvenue ). Il n'est donc pas "évident" de baser la décision sur le cout de copie, puisque les concepteurs de ce langage ont décidé de ne pas tenir compte de cet aspect (et non, ils ne sont pas cons, même s'ils décident en toute connaissance de cause d'aller à rebours des autres).
    Nous sommes d'accord sur le fait que les guru ne sont pas forcément d'accord entre eux, cependant:

    La copie est systématiquement un processus "lourd", qui "prend énormément de temps" (en comparaison avec d'autres processus) et qui peut demander "énormément de mémoire" (toute chose étant par ailleurs égales).

    Haskell est un langage fonctionnel et, comme la plupart des langages fonctionnels, il considère les paramètres de ses fonctions comme des valeurs constantes, car une fonction proche de y ->f(x) va impliquer le fait que "pour tout x" (respectant certaines conditions propres à l'ensemble considéré pour x), il y a une "valeur y" (respectant certaines conditions propres à l'ensemble envisagé pour y, qui peut être différent de l'ensemble envisagé pour x) telle que y sera le résultat des opérations définies dans f. Et, comme la plupart des langages fonctionnels, il ne pense pas en terme de variable, mais bien en termes de valeur. Or, une valeur est toujours constante ( 4 ne vaudra jamais que 4 : si, par une modification quelconque, tu passe à 5, à 10 ou à 1.5, tu as... une valeur tout à fait différente )

    "Tout programme en informatique n'aura jamais plus d'intelligence que celle que ses concepteurs auront été capables de lui donner". Les compilateur sont de plus en plus intelligents, certes, mais il souffrent encore de certaines restrictions. Et, de toutes facons, comme tu l'as si bien dit, c'est sans doute un débat pour les guru, qui sort amplement de la protée de cette discussion.

    Il n'empêche -- bien que cela m'écorche les doigts de l'admettre -- que cela a du bon de se souvenir de temps en temps qu'aucune règle n'est strictement absolue. Mais, si je l'admets beaucoup plus facilement ici, c'est surtout parce que les règles en question sont basées sur des assertions faite au sujet de "l'intelligence relative" des compilateurs.

    Et, dans ce cadre, le mieux est parfois de tout simplement "faire l'essai", et comparant -- à condition d'en être capable bien sur -- le code assembleur généré.
    Cela peut aller même plus loin: certains dispositifs informatiques tout à fait respectables (GPU!) ne peuvent même pas proposer, quel que serait le langage de programmation, certains types de références.
    Cela n'a pas grand chose à voir : certains langages présentent un très haut niveau d'abstraction par rapport aux instructions machine, d'autre présente un niveau d'abstraction moindre, et le GPU en lui-même est "en dessous de tout cela", vu qu'il s'agit... du matériel à proprement parler.

    Dés que l'on s'"attaque" à utiliser le gpu, il faudra de toutes facons que l'on "rabaisse" le niveau d'abstraction pour le faire correspondre... à la réalité des instructions que le gpu est capable de comprendre (qui ne sont -- faut il le rappeler -- au mieux qu'une succession de 0 et de 1, si pas une succession de "chemin de passage" pour le courant )

    Si les experts s'écharpent encore sur le sujet, c'est peut-être un poil trop stratosphérique pour nous autres mortels lecteurs de forum...
    Sur ce point particulier, j'aurais tendance à être d'accord
    Je recommande humblement tout de même de se poser la question lors du passage en argument dune donnée utilisée un peu partout, même lourde. Un conseil que je donne aux arrivants dans notre société est de se demander avant de faire une ref const "est-ce un pointeur vers de la ROM?"
    Je ne vois pas pourquoi tu le fais...

    Au final, ref (non const), c'est l'équivalent un pointeur constat (vers une valeur qui peut être modifiée) et ref const, c'est équivalent à un ponteur constant vers une variable constante. Le tout est donc simplement de savoir si on souhaite que la variable référencée (pointée) puisse être modifiée ou non.
    N'oublions pas que l'aspect sémantique de la "constness" en C++ est incomplet ou flou: il mélange l'interdiction de modifier avec la garantie que cela ne bougera pas.
    Je ne suis pas vraiment d'accord avec toi...

    Aucune donnée ne peut réellement être déplacée en mémoire, à moins d'être explicitement copiée de son adresse d'origine (ou du registre dans lequel elle se trouve) vers son adresse de destination. Le mot clé const, les références, les pointeurs n'ont rien à voir là dedans

    La seule chose qui pourrait s'en rapprocher, c'est que le système de références / de pointeurs fait le lien entre l'identifiant associé à une valeur (la "variable") et sa position en mémoire; avec une différence claire entre la notion de référence et de pointeur : on est libre de modifier l'adresse mémoire à laquelle est associée un pointeur, alors que nous ne pourrons pas associer une autre adresse mémoire à une référence.

    Et encore, si tu modifies la valeur d'un pointeur, tu ne fait que modifier l'adresse mémoire à laquelle tu espère pouvoir accéder à la valeur qui t'intéresse. Tu ne fais en aucun cas bouger tes données, qui resteront à chaque fois bien sagement à l'adresse mémoire qui leur a été assignée. D'ailleurs, si tu t'arrange pour être en mesure de redonner sa valeur d'origine au pointeur, la valeur que tu retrouveras à l'adresse mémoire en question sera exactement celle que ... tu y avais mise à l'origine

    Quand au mot clé const et l'aspect constness, c'est juste un grand panneau "regarder, pas toucher" que le compilateur est en mesure de respecter
    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

  9. #9
    Membre confirmé

    Inscrit en
    Août 2007
    Messages
    300
    Détails du profil
    Informations forums :
    Inscription : Août 2007
    Messages : 300
    Points : 527
    Points
    527
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Quand au mot clé const et l'aspect constness, c'est juste un grand panneau "regarder, pas toucher" que le compilateur est en mesure de respecter
    Je crois effectivement que mon message n'est pas passé. Ta phrase ci-dessus illustre exactement que le const du C++ ne précise que l'aspect "interdiction de modifier". Il y a par ailleurs quelque chose qui est important en embarqué et en parallèle massif: la "garantie que cela ne bougera pas", ce qui est proposé par copie ou dans des langages moins évolués par des tags ROM. Ce sujet est exactement ce qui est abordé par D. Abrahams dans son papier-fantôme "Want speed? Pass by value" de 2009, dont tu peux trouver de nombreuses traces et que je t'encourage à lire. On sait que ce point a affecté la conception du langage D (cf le 1.4 de ce lien).
    Tu verras certainement les discussions autour, qui montrent que le sujet est encore ouvert, et que si un consensus se dégage, c'est qu'il faut réfléchir au cas par cas: il vaut souvent mieux passer par valeur, mais ... pas toujours!

    Ce sont ces débats qui me font mettre un bémol à des affirmations comme celles de dalfab, camboui, ou ta propre phrase:
    Citation Envoyé par koala01 Voir le message
    La copie est systématiquement un processus "lourd", qui "prend énormément de temps" (en comparaison avec d'autres processus) et qui peut demander "énormément de mémoire" (toute chose étant par ailleurs égales)."
    Je me garderais bien de trancher. Ma petite technique ("est-ce qu'on pointe vers de la ROM?" - je travaille dans une société qui fait beaucoup d'embarqué) force par contre les programmeurs à se poser la bonne question, et à y répondre sans être aveuglé par le cout de la copie, qui est ou n'est pas prépondérant dans la décision de passer par valeur ou const ref par rapport à la contention de synchronisation possible, que tu expliques fort bien pour Haskell. Tu dis qu'aucune donnée n'est déplacée etc. (tes derniers paragraphes), mais ce n'est pas le sujet: si la zone pointée par le const ref est affectée par un autre processus (i.e. n'a pas la "garantie que cela ne bougera pas"), alors copier (passer par valeur) peut très bien être la meilleure chose à faire pour accélérer fortement le code, même sur des copies lourdes.
    "Maybe C++0x will inspire people to write tutorials emphasizing simple use, rather than just papers showing off cleverness." - Bjarne Stroustrup
    "Modern C++11 is not your daddy’s C++" - Herb Sutter

  10. #10
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 113
    Points : 32 958
    Points
    32 958
    Billets dans le blog
    4
    Par défaut
    Certes, mais on a à faire à un débutant, les optimisations liés aux multithreading et autres ne sont pas (encore, du tout) à l'ordre du jour.
    Bien sûr que si ton code est un thread qui traite la donnée et que la donnée risque d'être modifié, tu as tout intérêt à passer une copie. Mais c'est juste un banal problème de datarace.
    Mais ça me semble hors de propos et overkill dans ce cas, et dans la majorité des cas. Ton travail n'est pas la majorité des cas mais est un cas particulier si tu en as autant besoin, tout comme dans un précédent poste en embarqué j'utilisais des reinterpret_cast partout parce qu'on avait tout en ROM, reinterpret_cast reste quelque chose de marginal pour la majorité des programmeurs et programmes.
    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.

  11. #11
    Membre expert
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    1 415
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mars 2007
    Messages : 1 415
    Points : 3 156
    Points
    3 156
    Par défaut
    Citation Envoyé par ac_wingless Voir le message
    Il y a par ailleurs quelque chose qui est important en embarqué et en parallèle massif: la "garantie que cela ne bougera pas"
    Celà a un nom et s'appelle l'immutabilité. C'est l'argument principal des langages qui se veulent distribués par nature tels que Erlang et Scala. C'est un sujet à la mode en Go et en Javascript bien que l'enjeu soit différent de l'embarqué. Effectivement, const ne fournit pas l'immutabilité. Mais elle peut s'implémenter en C++, avec un peu de rigueur.

    En effet je pense qu'on dépasse le besoin du posteur original là.
    Find me on github

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 518
    Points
    41 518
    Par défaut
    Citation Envoyé par jblecanard Voir le message
    Effectivement, const ne fournit pas l'immutabilité. Mais elle peut s'implémenter en C++, avec un peu de rigueur.
    Si j'ai bien compris ac_wingless, le problème n'est pas de l'implémenter, mais de signaler à l'optimiseur qu'on l'a fait.

    Edit: D'un autre côté, n'est-ce pas aussi ce à quoi sert restrict, qui signale une garantie d'absence d'aliasing? Un paramètre const restrict doit probablement être supposé ne changeant jamais...
    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.

  13. #13
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 186
    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 186
    Points : 17 126
    Points
    17 126
    Par défaut
    Tu veux dire register?
    Avant C++17, une variable peut-être déclarée register, mais cela ne change rien du tout.
    Après C++17, ce n'est même plus possible.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 518
    Points
    41 518
    Par défaut
    Non, je disais bien restrict. Mais peut-être est-ce resté spécifique au C, à l'instar d'autres améliorations du C99 comme les VLA?
    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.

  15. #15
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 186
    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 186
    Points : 17 126
    Points
    17 126
    Par défaut
    C'est effectivement propre au C, et c'est apparu en C99.
    Je me disais bien que ca me disait quelque chose, cette signification.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  16. #16
    Membre habitué
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Mai 2014
    Messages
    227
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2014
    Messages : 227
    Points : 162
    Points
    162
    Par défaut
    Merci à tous pour ces réponses, pour le coup je suis toujours perdu pour savoir quand faire une copie ou non x). Après pas mal de recherche et pas mal d'apprentissages sur plusieurs sites/forums sur la const-correctness, les réf, les copies, les classes "Global"/Manager... J'ai revue entièrement ma façon de faire, j'ai compris qu'une classe manager est un défaut de conception en soit, car, ça n'as pas vraiment de sens et ça ne veut pas définir grand-chose (De la gestion des gestionnaires). J'ai fait finalement beaucoup plus simple, pour gérer mes boutons je les stocke dans une map avec une clef de type Enum (je ne sais pas si ça ce dit). Pour toutes les textures que je vais utilisé je fait de même, je les stockes dans une map et pour passer la texture à un bouton par exemple, je fait une recherche dans ma map de texture avec comme clef le type du bouton défini par une Enum. Si les Enums correspondent j'applique à mon bouton une texture via
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    void setTexDef( const sf::texture *texDef ){ texture_default_ = texDef; }
    sinon je lui applique une texture "vide" et je renvoie une erreur (try throw).
    Il reste quand même une chose où je bloque un peu, c'est le chargement des textures. Je veux par la suite pouvoir faire évoluer/modifier mon jeu sans devoir le recompiler. Donc pour chargé les textures j'avais pensé à créer un fichier contenant les adresses des textures ainsi que leurs clefs, mais es que c'est la bonne méthode ?

  17. #17
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 186
    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 186
    Points : 17 126
    Points
    17 126
    Par défaut
    Une idée serait d'avoir un identifiant de texture dans les fichiers de données, et d'avoir une map de ces identifiants vers les (pointeurs de) textures dans le code de chargement.

    Quitte à utiliser directement les adresses une fois les données utilisées pour le code de l'affichage.
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

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

Discussions similaires

  1. Problème de pointeurs..embrouillé
    Par Frenchy dans le forum C++
    Réponses: 11
    Dernier message: 10/03/2005, 17h33
  2. Problème de pointeur avec un TQuery
    Par Oluha dans le forum Bases de données
    Réponses: 3
    Dernier message: 25/01/2005, 14h57
  3. Problème de pointeur
    Par toma_lille dans le forum C++
    Réponses: 1
    Dernier message: 07/12/2004, 22h26
  4. [MFC] Problème de pointeur !!
    Par acastor dans le forum MFC
    Réponses: 7
    Dernier message: 19/03/2004, 16h50
  5. TBitmap et problèmes de pointeurs...
    Par benj63 dans le forum C++Builder
    Réponses: 8
    Dernier message: 28/07/2003, 14h39

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