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 :

Demande d'avis sur des pointeurs intelligents


Sujet :

C++

  1. #1
    Membre confirmé
    Inscrit en
    Mars 2006
    Messages
    209
    Détails du profil
    Informations forums :
    Inscription : Mars 2006
    Messages : 209
    Par défaut Demande d'avis sur des pointeurs intelligents
    Bonjour à vous tous !!.

    J’espère que vous allez bien, et que pour ceux qui ont passé le bac ont réussis et qu'ils ont obtenus les vœux souhaité.

    Si je viens vous voir, ce n'est pas spécialement pour vous demander de l'aide (pour une fois (a) ), mais bien pour avoir un avis sur mon code.

    Je viens du langage C (langage que j'apprécie beaucoup, donc pas de troll le C c'est pourri ^^ ), mais j'ai envie d'apprendre du C++. D'après ce que j'ai vu, ce "passage" peut donner de mauvaises habitudes, etc etc, donc je veux savoir si je code dans un C++ correct ou vraiment super moche horrible (n'hésitez pas à le dire, c'est comme ça qu'on progresse ).

    Bref, je ne suis pas là pour vous présentez du code super optimisé, mais juste un code sécurisé, en fait j'ai décider de "reprendre" l'idée des auto_ptr et de les "améliorer". Donc l'idée est simple, le pointeur peut se faire copier, je gère le nombre de référence etc etc. J'ai corriger toutes mes erreurs que j'ai put trouver à l'aide de valgrind, donc je pense qu'il est fonctionnel.

    A part pour les itérateurs, que j'ai implémenter à la one again et bistoufly (car je n'en suis pas encore aux itérateurs en fait), je pense que j'ai fait du travail plus ou moins correct.

    J'ai essayer d'imiter le plus possible le comportement d'un pointeur : Opérateur * -> [] ++ -- post et préFixé, += -=, + - etc.

    Voilà mon code, si vous trouvez des erreurs, segfault, fuites de mémoires, merci de me le dire.

    main.cpp
    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
    #include <iostream>
     
    #include "QGM_Ptr.h"
     
    using namespace std;
     
    int main(void)
    {
        qgm::smart_ptr<int> tableau(100);
     
        qgm::smart_ptr<int> pointeurSurLaPremiereCase;
        qgm::smart_ptr<int> ptr;
     
        pointeurSurLaPremiereCase = tableau;
     
        for(int i = 0; i < 102; ++i){
        	try{
    	    *tableau++ = i;
     	}
     
    	catch(exception &e){
    	    cout << e.what() << endl;
    	}
        }
     
        for(int i = 0; i < 102; ++i){
        	try{
    	    cout << pointeurSurLaPremiereCase[i] << " ";
        	}
     
        	catch(exception &e){
    	    cout << e.what() << endl;
        	}
        }
     
        try{
     	// Pointeur = première case du tableau 
       	ptr = -100 + tableau;
     
      	// On affiche
       	cout << endl << *ptr << endl;
        }
     
        catch(exception &e){
    	cout << e.what() << endl;
        }
     
        // On supprime
        ptr.release();
     
        // Doit affiche qgm::bad_ptr
     
        try{
    	    cout << *pointeurSurLaPremiereCase << " ";
        }
     
        catch(exception &e){
      	cout << e.what() << endl;
        }
     
        ptr.alloc(200);
        tableau = ptr;
     
        qgm::smart_ptr<int>::iterator it = tableau.begin();
     
        for(; it != tableau.end(); ++it)
    	*it = 0;
     
        for(it = ptr.begin(); it != ptr.end(); ++it)
            cout << *it << " ";
     
        return 0;
    }
    QGM_types.h
    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
    #ifndef QGM_TYPES_H_INCLUDED
    #define QGM_TYPES_H_INCLUDED
     
    namespace qgm{
        typedef signed char    s8;
        typedef unsigned char  u8;
     
        typedef signed short   s16;
        typedef unsigned short u16;
     
        typedef signed long    s32;
        typedef unsigned long  u32;
     
        typedef signed int     sint;
        typedef unsigned int   uint;
     
        typedef float          f32;
        typedef double         f64;
    }
     
    #endif // QGM_TYPES_H_INCLUDED
    qgm_ptr (le plus important haha)
    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
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330
    331
    332
    333
    334
    335
    336
    337
    338
    339
    340
    341
    342
    343
    344
    345
    346
    347
    348
    349
    350
    351
    352
    353
    354
    355
    356
    357
    358
    359
    360
    361
    362
    363
    364
    365
    366
    367
    368
    369
    370
    371
    372
    373
    374
    375
    376
    377
    378
    379
    380
    381
    382
    383
    384
    385
    386
    387
    388
    389
    390
    391
    392
    393
    394
    395
    396
    #ifndef QGM_PTR_H_INCLUDED
    #define QGM_PTR_H_INCLUDED
     
    #include <map>
    #include <exception>
    #include <string>
    #include "QGM_Types.h"
     
    namespace qgm
    {
        class bad_ptr : public std::exception
        {
            public :
                bad_ptr(void) throw() : p("qgm::bad_ptr"){}
     
                virtual char const *what(void) const throw(){
                    return p.c_str();
                }
     
                virtual ~bad_ptr(void) throw(){}
     
            private :
                std::string p;
        };
     
        class out_of_range_ptr : public std::exception
        {
            public :
                out_of_range_ptr(void) throw() : p("qgm::out_of_range_ptr"){}
     
                virtual char const *what(void) const throw(){
                    return p.c_str();
                }
     
                virtual ~out_of_range_ptr(void) throw(){}
     
            private :
                std::string p;
        };
     
        template<typename Type>
        class smart_ptr{
            /** Class gérant les pointeurs alloués sur le tas **/
     
            public :
                /** Ce constructeur permet d'avoir accès à un tableau dynamique
                        de taille définie **/
                explicit smart_ptr(u32 size);
     
                /** Construit un pointeur intelligent à partir d'un pointeur.
                        Si isArrayNelem == 0 : Le pointeur est alloué avec new
                        Si isArrayNelem >= 1 : Le pointeur est alloué avec new[]
                            et contient le nombre de "cases préallouées"
                    De base, on alloue avec new **/
                smart_ptr(Type *ptr, u32 isArrayNelem = 0);
     
                /** Constructeur de copie **/
                smart_ptr(smart_ptr const &ptr);
     
                /** Opérateur d'affection **/
                smart_ptr &operator=(smart_ptr const &ptr);
     
                /** Construit un pointeur NULL **/
                smart_ptr(void);
     
                /** Définie pour struct->membre **/
                Type *operator->(void);
     
                /** int i = *(int*)pInt; **/
                Type &operator*(void);
     
                /** int n = tableau[5]; **/
                Type &operator[](s32 index);
     
                /** Operateur += et -=  **/
                smart_ptr &operator+=(s32 i);
                smart_ptr &operator-=(s32 i);
     
                /** Opérateur d'incrémentation préFixé **/
                smart_ptr &operator++(void);
                smart_ptr &operator--(void);
     
                /** Opérateur d'incrémentation postFixé **/
                smart_ptr operator++(sint);
                smart_ptr operator--(sint);
     
                /** Permet d'allouer le pointeur **/
                void alloc(u32 size = 1);
     
                /** Permet de libérer le pointeur **/
                void release(void);
     
                /** Destructeur **/
                ~smart_ptr(void);
     
     
    	    /** Les itérateurs **/
    	    typedef Type* iterator;
     
    	    Type *begin(void){return m_Begin;}
    	    Type *end(void)  {return m_End;  }
     
            private :
                Type *m_Ptr;
                Type *m_Begin;   // Pointeur poinant sur le premier élément
                Type *m_End;     // Pointeur sur l'élément suivant le dernier
                bool  m_IsArray; // Est ce que le tableau est alloué avec new([])
     
                /** Remet à 0 l'objet **/
                void setZero(void);
     
                /** Retire une référence et détruit le pointeur si besoin **/
                void subPtr(void);
     
                /** Test le pointeur **/
                void testPointer(void);
        };
     
        /** Tableau associatif pour clé un pointeur
                et comme valeur le nombre de référence à ce pointeur **/
        static std::map<void*, u32> ptrMap;
     
        typedef std::map<void*, u32>::iterator iteratorPtrMap;
     
        template<typename Type>
        void smart_ptr<Type>::setZero(void){
            m_Ptr = m_Begin = m_End = 0;
            m_IsArray = false;
        }
     
        template<typename Type>
        void smart_ptr<Type>::subPtr(void){
            iteratorPtrMap it = ptrMap.find(m_Begin);
     
            /** si le pointeur existe **/
            if(it != ptrMap.end()){
                if(--it->second == 0){ // Si il n'est plus utilisé on supprime
                    ptrMap.erase(it);
     
                    if(m_IsArray == true)
                        delete[] m_Begin;
     
                    else
                        delete   m_Begin;
     
                    setZero(); // On remet = 0 le pointeur
                }
            }
        }
     
        template<typename Type>
        void smart_ptr<Type>::testPointer(void){
            iteratorPtrMap it = ptrMap.find(m_Begin);
     
            // si le pointeur n'est pas trouvé, on lève une exception
            if(it == ptrMap.end())
                throw bad_ptr();
        }
     
        /** Constructeurs **/
        /** Constructeur NULL **/
        template<typename Type>
        smart_ptr<Type>::smart_ptr(void) :
        m_Ptr(0),
        m_Begin(0),
        m_End(0),
        m_IsArray(false){
        }
     
        /** Constructeur récupérant un pointeur **/
        template<typename Type>
        smart_ptr<Type>::smart_ptr(Type *ptr, u32 isArrayNelem) :
        m_Ptr(ptr),
        m_Begin(ptr),
        m_End(ptr + (isArrayNelem == 0 ? 1 : isArrayNelem)),
        m_IsArray(isArrayNelem == 0 ? false : true){
            /** Si ce n'est pas un tableau **/
            if(isArrayNelem == 0)
            {
                m_End = ptr + 1;
                m_IsArray = false;
            }
     
            else
            {
                m_End = ptr + isArrayNelem;
                m_IsArray = true;
            }
     
            ptrMap[m_Begin] = 1; // une utilisation
        }
     
        /** Constructeur allouant une certaines place **/
        template<typename Type>
        smart_ptr<Type>::smart_ptr(u32 size):
        m_Ptr(new Type[size]),
        m_Begin(m_Ptr),
        m_End(m_Ptr + size),
        m_IsArray(true){
            ptrMap[m_Begin] = 1; // une utilisation
        }
     
        /** Constructeur de copie **/
        template<typename Type>
        smart_ptr<Type>::smart_ptr(smart_ptr const &ptr) :
        m_Ptr(ptr.m_Ptr),
        m_Begin(ptr.m_Begin),
        m_End(ptr.m_End),
        m_IsArray(ptr.m_IsArray){
            iteratorPtrMap it = ptrMap.find(m_Begin);
     
    	/** Si le pointeur existe **/
    	if(it != ptrMap.end())
    	    ++it->second;
        }
     
        /** Opérateur = **/
        template<typename Type>
        smart_ptr<Type> &smart_ptr<Type>::operator=(smart_ptr const &ptr){
            if(m_Ptr == ptr.m_Ptr)
                return *this;
     
            subPtr();
     
            m_Ptr   = ptr.m_Ptr;
            m_Begin = ptr.m_Begin;
            m_End   = ptr.m_End;
     
            m_IsArray = ptr.m_IsArray;
     
            if(m_Ptr != 0)
                ++ptrMap[m_Begin]; // On ajoute une utilisation
     
            return *this;
        }
     
        /** Fonctions d'allocations / désallocations **/
        template<typename Type>
        void smart_ptr<Type>::alloc(u32 size)
        {
            /** Si on cherche à allouer mais que c'est déjà pris **/
            subPtr();
     
            m_Ptr = new Type[size];
            m_Begin = m_Ptr;
            m_End = m_Ptr + size;
            m_IsArray = true;
        }
     
        template<typename Type>
        void smart_ptr<Type>::release(void){
            iteratorPtrMap it = ptrMap.find(m_Begin);
     
            if(it == ptrMap.end())
                return;
     
            else{
                if(m_IsArray == true)
                    delete[] m_Begin;
     
                else
                    delete m_Begin;
            }
     
            setZero();
            ptrMap.erase(it);
        }
     
        /*************************************************************************/
        /** Opérateurs * -> [] **/
     
        template<typename Type>
        Type &smart_ptr<Type>::operator*(void){
            testPointer();
            return *m_Ptr;
        }
     
        template<typename Type>
        Type *smart_ptr<Type>::operator->(void){
            testPointer();
     
            if(m_Ptr < m_Begin || m_Ptr >= m_End)
                throw out_of_range_ptr();
     
            return *m_Ptr;
        }
     
        template<typename Type>
        Type &smart_ptr<Type>::operator[](s32 index){
            testPointer();
     
            Type *ptr = m_Ptr + index;
     
            if(ptr < m_Begin || ptr >= m_End)
                throw out_of_range_ptr();
            return *ptr;
        }
     
        /** Operateur += et -=  **/
        template<typename Type>
        smart_ptr<Type> &smart_ptr<Type>::operator+=(s32 i){
            testPointer();
     
            Type *ptr = m_Ptr + i;
     
            /** Le pointeur à le droit de pointé sur m_End **/
            if(ptr < m_Begin || ptr > m_End)
                throw out_of_range_ptr();
     
            m_Ptr = ptr;
            return *this;
        }
     
        /** Operateur += et -=  **/
        template<typename Type>
        smart_ptr<Type> &smart_ptr<Type>::operator-=(s32 i){
            testPointer();
     
            Type *ptr = m_Ptr - i;
     
            /** Le pointeur à le droit de pointé sur m_Begin **/
            if(ptr < m_Begin || ptr > m_End)
                throw out_of_range_ptr();
     
            m_Ptr = ptr;
            return *this;
        }
     
        /** Opérateur d'incrémentation préFixé **/
        template<typename Type>
        smart_ptr<Type> &smart_ptr<Type>::operator++(void){
            return *this += 1;
        }
     
        template<typename Type>
        smart_ptr<Type> &smart_ptr<Type>::operator--(void){
            return *this -= 1;
        }
     
        /** Opérateur d'incrémentation postFixé **/
        template<typename Type>
        smart_ptr<Type> smart_ptr<Type>::operator++(sint){
            smart_ptr<Type> ptr(*this);
     
            ++*this;
     
            return ptr;
        }
     
        template<typename Type>
        smart_ptr<Type> smart_ptr<Type>::operator--(sint){
            smart_ptr<Type> ptr(*this);
     
            --*this;
     
            return ptr;
        }
     
        /** opérateur + et - de type : ptr + x **/
        template<typename Type>
        smart_ptr<Type> operator+(smart_ptr<Type> const &ptr1, s32 i){
            smart_ptr<Type> ptr(ptr1);
     
            ptr += i;
     
            return ptr;
        }
     
        template<typename Type>
        smart_ptr<Type> operator-(smart_ptr<Type> const &ptr1, s32 i){
            smart_ptr<Type> ptr(ptr1);
     
            ptr -= i;
     
            return ptr;
        }
     
        /** Opérateur + et - de type : x + ptr **/
        template<typename Type>
        smart_ptr<Type> operator+(s32 i, smart_ptr<Type> const &ptr1){
            return smart_ptr<Type>(ptr1 + i);
        }
     
        template<typename Type>
        smart_ptr<Type> operator-(s32 i, smart_ptr<Type> const &ptr1){
            return smart_ptr<Type>(ptr1 - i);
        }
     
        /** Destructeur **/
        template<typename Type>
        smart_ptr<Type>::~smart_ptr(void){
            subPtr(); // On enlève une référence
        }
    }
     
    #endif // QGM_PTR_H_INCLUDED
    Merci de vos conseils

  2. #2
    Membre Expert

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Par défaut
    Bonjour,

    J'ai pas lu dans les détails, mais quelques remarques :


    1. L'évolution de std::auto_ptr (déprécié à l'heure actuelle) existe déjà et se nomme std::unique_ptr.
    2. L'équivalent de ce que tu as codé existe aussi et se nomme std::shared_ptr.
    3. La responsabilité des classes de pointeur intelligent c'est de s'occuper de la libération des ressources selon une politque déterminée. Ainsi ton constructeur explicite n'a, AMA, pas trop sa place ici.
    4. Pour ton opérateur d'affectation : idiom copy-and-swap.
    5. Tu as un réel intérêt à utiliser une std::map<void*,u32> à la place d'un u32* en guise de compteur dans les instances ? (u32* ou plus évolué, peu importe) (*)
    6. Les opérateurs d'arithmétiques sur les pointeurs intelligent me gènent un peu. Il est vrai que les pointeurs intelligent doivent avoir une sémantique de pointeur. Sauf que cette arithmétique casse quand même un peu la notion de ressource, on ne lui dit plus "occupes toi de ca pour moi" mais "occupe toi de cet endroit". Et tu oublies de mettre à jour tes conteurs dans ces opérations d'ailleurs.
    7. L'idée de gérer en même temps les tableaux et les pointeurs simples ne me gène pas, cependant trouver dans l'interface de la classe une opération qui n'a potentiellement aucun sens (operator[]) me gène un peu plus. Je vois deux approches :
      • Tu considères que la ressource gérée est le tableau dans son ensemble, et dans ce cas il n'y a pas de raison de fournir d'opérateur [] : il s'occupe juste de gérer le tableau, pas d'y accéder.
      • Tu considères qu'il gère un ensemble d'éléments consécutifs, et dans ce cas tu peux le faire en créant une spécialisation (pour T[]), pour gérer ce cas.
    8. Toujours sur les tableaux et pour le premiers cas, on peut aller plus loin. En effet tu réalises une classe gérant une ressource, qu'est ce qui change entre les deux types de ressources ? La facon de la détruire : delte, delete []. On pourrait d'ailleurs imaginer des ressources qui ont un processus de destruction qui peut être plus complexe qu'un simple delete. L'idée pourrait être alors d'ajouter un paramètre optionnel à ton constructeur et/ou ta liste de paramètre template (je te laisse réflechir à la différence que ca introduit et aux éventuelles utilités), qui permettrait de faire cette libération de la ressource. Ainsi au final ta classe s'occuperais principement de savoir quand libérer les ressource, et laisserais cette tâche à ce nouveaux paramètre qui serait alors la politique de destruction.
    9. Ton style de programmation est très défensif je trouve. Les divers vérifications que tu fais devraient plutôt être des assertions à mon avis. Dans le sens où si elles échouent alors c'est une erreur du programmeur.
    10. Je n'ai pas fait attention, mais si tu veux rendre ta classe utilisable en MT, il faut faire attention, entre autre le compteur doit être atomique.
    11. Si tu veux aller plus loin, il y a un chapitre qui traite des pointeurs intelligents dans MC++D, et la lecture du code des pointeurs intelligent de boost (au moins l'interface) et de l'interface proposé dans la bibliothèque standard peut se révéler instructif. (D'ailleurs l'ensmble de mon message s'inspirer de ces 3 ressources)


    (*) Je vois bien un intérêt réel, cependant les implémentations actuelles des pointeurs intelligent considèrent que l'utilisateur demande explicitement la gestion de la ressource lorsqu'il construit le pointeur intelligent. Et qu'ainsi si il construit deux fois le pointeur intelligent depuis la même ressource c'est qu'il demande explictement de la gérer deux fois, par contre tant qu'il manipule le pointeur intelligent (copie/affectation) alors elle est bien gérée comme une seule et même ressource.

  3. #3
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Par défaut

    Pour rappel, JolyLoic avait écrit un tutoriel sur les pointeurs intelligents et présentait une approche pour créer sa propre classe de pointeur : http://loic-joly.developpez.com/tuto...mart-pointers/
    A lire

  4. #4
    Membre Expert

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Par défaut
    <HS>
    Il ne faudrait pas faire un MaJ ou une note de bas de page concernant la partie de cet article utilisant les concepts qui auraient du être dans le C++11 et qui n'y sont finalement pas ?
    </HS>

  5. #5
    Membre confirmé
    Inscrit en
    Mars 2006
    Messages
    209
    Détails du profil
    Informations forums :
    Inscription : Mars 2006
    Messages : 209
    Par défaut
    Salut, déjà merci de vos réponses .

    1) Pour unique ptr, je pense qu'il possède le même problème que auto_ptr (les copies etc ^^ ).

    2) Ha, je pensais qu'il n'étais pas encore standard (pour ça que je code ça)^^.

    3) Pour moi, je trouve ça plus facile, mais tu as raison cependant .

    4) J'incrémente la référence donc c'est bon non?

    5) C'était plus facile à gérer pour moi ^^ Ton explication est plutôt compliqué pour moi ^^.

    6) Le compteur est apparemment bien gérer, je n'ai pas eu de problème avec les recopies ni incrémentations etc pourtant...

    7) Les spécialisations, je n'en suis pas encore, sinon oui, j'essayais de reproduire le plus fidèlement possible les pointeurs.

    8) Effectivement, c'est une très bonne idée, ça m'aurait enlever pas mal de problème de conception .

    9) Effectivement, je n'y avais pas penser...

    10) MT et atomique? Je n'ai pas compris...

    11) je ne connais pas MC++D. Pour Boost, d'après ce que j'ai compris, si Linus Torvald à la haine contre le C++, c'est surtout pour des raisons de portabilité à cause de Boost. Sinon, ben, faut voir comment je peux regarder comment est coder et l'interface et le code des pointeurs.

    Moralité : Etant donné que les shared_ptr sont standard, je vais utiliser ceux là .

    Pour le tuto, ben je lirais ça plus tard ^^.

  6. #6
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Par défaut
    2) c'est standard dans la nouvelle norme (et avant cela, c'était dans la norme TR1) et implémenté dans certains compilateur depuis des années (gcc)

    10) MT = multithread ; atomique = opération qui ne peut être intérompu avant la fin de son déroulement (wiki)

    11) non, parce que c'est un crétin fermé sur son monde

  7. #7
    Membre émérite
    Avatar de Ekleog
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    448
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 448
    Par défaut
    1) Non, il a un move-constructor, qui déplace le pointeur, mais refuse toute copie. En gros, il retire toute possibilité d'erreur d'inattention.

    4) En fait, tu simplifierais l'operator= avec un copy&swap.

    6) Il trouve juste que les operateurs + et autres sont de trop pour un pointeur intelligent. Après, on peut argumenter. (Flob> Il n'y a pas de problème de compteurs, si tu considères qu'un operator + ou autre a pour principe de s'occuper d'un espace mémoire, et qu'il peut pointer temporairement n'importe où sur cet espace.)

    11) Non, c'est juste un gros trolleur.

    Moralité: Les unique_ptr sont encore mieux que les shared_ptr, parce qu'ils permettent de définir explicitement la notion de propriété d'un objet.

  8. #8
    Membre confirmé
    Inscrit en
    Mars 2006
    Messages
    209
    Détails du profil
    Informations forums :
    Inscription : Mars 2006
    Messages : 209
    Par défaut
    Je vais me renseigner sur tout ça.

    L'idée, c'est que comme expliqué dans le tutoriel donné précédemment, je puisse allouer un pointeur dans une fonction et le redistribuer tout à l'heure (en passant, j'ai même pas essayer avec mon code à moi xD ).

    Pour le 4 je vois pas trop, mais peut être est ce expliqué plus loin dans mon livre ou dans le tutoriel donné ^^.

    Pour Linus, je veux bien croire que ce soit un trolleur ou quoi que ce soit, mais je pense pas qu'il soit crétin, coder un noyau comme Linux n'est pas à la portée de n'importe qui.

    Moi je pense qu'il a vut des codes vraiment affreux en C++ et qu'il trouve que le C++ est plus compliqué que le C ( ce que je trouve vrai avec tous les concepts implantés ), enfin bon ne lançons pas ce débat inutile . ^^

    Merci pour votre aide.

  9. #9
    Membre émérite
    Avatar de Ekleog
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2012
    Messages
    448
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2012
    Messages : 448
    Par défaut
    Pour Linus, je veux bien croire que ce soit un trolleur ou quoi que ce soit, mais je pense pas qu'il soit crétin, coder un noyau comme Linux n'est pas à la portée de n'importe qui.
    Il y a crétin et crétin, hein.
    Et puis, ce n'est pas comme si il avait fait tout linux tout seul, non plus.
    Après, loin de moi l'idée de le dénigrer !

    Moi je pense qu'il a vut des codes vraiment affreux en C++ et qu'il trouve que le C++ est plus compliqué que le C ( ce que je trouve vrai avec tous les concepts implantés ), enfin bon ne lançons pas ce débat inutile . ^^
    Et moi, j'ai vu des codes vraiment affreux en C, hein.
    Surtout quand j'en vois qui tente de faire de l'OO avec un outil qui n'est pas fait pour. Oui, qui essaie de visser (OO) avec un marteau (C).
    Non, je ne parle pas du noyau linux.

    Enfin, c'est quand même amusant de voir que les gros projets en C en finissent quasiment tous par réinventer l'OO, et même la virtualité, avec des vtables main...

  10. #10
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Par défaut
    [HS]
    Crétin dans son comportement, pas dans ses compétences techniques. Quelqu'un qui se comporterait comme lui sur le forum prendrait directement un carton pour troll Quand on a sa "visibilité", se comporter en adolescent gâté avec ses "ce que je connais, c'est le mieux, le reste c'est moisi" donne pas forcement l'image que les développeurs sont des gens intelligents.
    Quand à la critique du C++, on n'a pas besoin de développeurs C pour le faire, les experts C++ (ceux qui bossent sur la norme, ceux qui bossent sur boost, les noms qu'on cite régulièrement) sont des gens intelligents et connaissent très bien les problèmes et limitations du C++ (et il y en a). Et franchement, je préfère avoir l'avis de gens qui connaissent de quoi ils parlent, combien de fois j'entends "je connais pas très bien, mais c'est nul"
    [fin HS]

  11. #11
    Membre confirmé
    Inscrit en
    Mars 2006
    Messages
    209
    Détails du profil
    Informations forums :
    Inscription : Mars 2006
    Messages : 209
    Par défaut
    Oui mais je disais pas ça méchemment tu sais, je débute moi, surtout en C++ :p.

    Je dis juste que je comprennais pas pourquoi il disait que boost n'est pas 100% portable? C'est toujours valable? Apparemment non

  12. #12
    Membre Expert

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Par défaut
    6) En effet le compteur est bon (j'avais oublié que tu considérais une plages de données et que tu pointais dedans).

    11) Au dela de te conseiller d'utiliser boost (*), je voulais surtout t'inviter à consulter l'interface (et donc la conception) que boost avait choisi pour ces classes de pointeurs intelligent.

    @Ekleog: En changeant la resposabilité de ta classe de pointeur intelligent c'est certain qu'elle fait ce que tu veux .

    (*) Je te le conseil quand même, bien que maintenant avec le C++11 on puisse plus facilement s'en passer.

  13. #13
    Membre Expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Par défaut
    Citation Envoyé par qnop Voir le message
    Oui mais je disais pas ça méchemment tu sais, je débute moi, surtout en C++ :p.
    Conclusion: n'utilises pas l'avis des autres (surtout de de Torval) pour faire des choix techniques. Compares les arguments techniques uniquement, dans le contexte précis de ton projet.

    Par exemple, une bonne raison de ne pas utiliser boost c'est qu'on te l'as interdit, ou encore que le compilateur n'est pas assez bien implémenté pour que toutes les libs boost compilent chez toi (notemment sur certains matériels embarqués bien fermés ou ya pas le choix du compilo...).
    Ce sont des arguments très rares au final.

    Un autre argument est si tu as besoin de maintenir l'ABI d'une bibliothèque pour un souci de manipulations des binaires au runtime (comme fait CPPCMS) auquel cas boost ne peut être utilisé puisqu'il ne peut pas garantir qu'il n'y aura pas de changement d'ABI entre les versions.

    Autrement dit, il y a peu de chances pour que tu ais un bon argument pour ne pas utiliser boost.

    Compare avec les "arguments" de Torvald...

    Je dis juste que je comprennais pas pourquoi il disait que boost n'est pas 100% portable? C'est toujours valable?
    Boost est toujours portable sur un max d'architectures et de compilos, mais entre les versions il peu y avoir des ratés. Donc suffit de se renseigner si la dernière version est utilisable dans ton cas (ou de juste tenter une compilation).
    Sinon le problème de stabilité d'ABI de boost est notable dans le cas que je cite au dessus, mais tu as rarement besoin d'avoir une ABI stable. Quand c'est le cas au pire tu peux tout simplement éviter d'exposer les elements de la bibliothèque dans l'interface de ta propre bibliothèque.

    Donc si il parlait de l'ABI, uniquement dans ce cas il a raison parcequ'il est dans un cas ou l'ABI a besoin d'être aussi stable que possible. Hors de ce cas, boost est portable.

Discussions similaires

  1. Demande d'avis sur un bouquin (Deitel)
    Par oodini dans le forum C++
    Réponses: 7
    Dernier message: 26/02/2005, 01h50
  2. Votre avis sur des morceaux de resumes
    Par Asarnil dans le forum C++
    Réponses: 5
    Dernier message: 03/01/2005, 15h22

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