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 :

Affectation possible par opérateur "=" même si pas définie


Sujet :

C++

  1. #1
    Membre confirmé
    Inscrit en
    Juin 2008
    Messages
    140
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 140
    Par défaut Affectation possible par opérateur "=" même si pas définie
    Bonjour,

    je suis face à un question que je n'arrive à répondre.
    Voici le code :
    Code C++ : 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
    #include <iostream>
    #include <new>
     
    class Test
    {
        private:
        int * m_nbr;
     
        public:
        Test( void ): m_nbr( 0 )
        {
            m_nbr = new( std::nothrow ) int;
            if( 0 != m_nbr )
                *m_nbr = 0;
        }
        Test( int aNbr ): m_nbr( 0 )
        {
            m_nbr = new( std::nothrow ) int;
            if( 0 != m_nbr )
                *m_nbr = aNbr;
        }
        Test( Test const & aTest ): m_nbr( 0 )
        {
            m_nbr = new( std::nothrow ) int;
            if( 0 != m_nbr )
                *m_nbr = *aTest.m_nbr;
        }
        ~Test( void )
        {
            std::cout << "delete" << std::endl; // rajouté pour indiquer que les instances sont bien supprimées.
            delete( m_nbr );
        }
        int getNbr( void ) const
        {
            if( 0 == m_nbr )
                return( 0 );
            else
                return( *m_nbr );
        }
        int * getPtNbr( void ) const
        {
            return( m_nbr );
        }
        void print( void )
        {
            std::cout << "(" << m_nbr << "," << *m_nbr << ")";
        }
    };
     
    int main( void )
    {
        int * thePtNbr( 0 );
        {
            Test theTest1;
            std::cout << "Test1: ";
            theTest1.print();
            std::cout << std::endl;
     
            thePtNbr = theTest1.getPtNbr();
     
            Test theTest2( 2 );
            std::cout << "Test2: ";
            theTest2.print();
            std::cout << std::endl;
     
            theTest1 = theTest2;
            std::cout << "Test1: ";
            theTest1.print();
            std::cout << std::endl;
        }
        std::cout << "(" << thePtNbr << "," << *thePtNbr << ")" << std::endl;
     
        return( 0 );
    }
    Je ne comprends pas pourquoi l'affection "theTest1 = theTest2;" fonctionne alors que l'opérateur "=" n'est pas définie pour cette classe Test. Cela provoque de surcroit une fuite mémoire (comme le montre la ligne avant le return du main). Par ailleurs, cela ne pose aucun problème lors de la destruction de "theTest2" de détruire "m_nbr" qui a normalement été détruit lors de la destruction de "theTest1".

    J'ai par ailleurs essayé en ne mettant uniquement le constructeur par défaut de la classe Test : "Test( void )", mais j'ai le même résultat.
    Pour informations, je compile avec MinGW, g++ version 4.7.2.

    Merci beaucoup pour vos indications.

  2. #2
    Membre Expert Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Par défaut
    Bonjour
    Tout est expliqué dans la FAQ
    http://cpp.developpez.com/faq/cpp/?p...GE_affectation
    La seconde chose à savoir est que le compilateur génère un opérateur d'affectation automatiquement si vous ne le faites pas, et que celui-ci sera suffisant dans la plupart des cas. Vous pouvez donc parfois tout simplement éviter de l'écrire.

    Il faudra écrire explicitement un opérateur d'affectation dès lors qu'une simple affectation membre à membre des données de votre classe n'est plus suffisante, par exemple si elle gère une ressource (un pointeur brut, une connexion à une base de données, une texture en mémoire vidéo, ...).

    Il existe également des situations où l'on ne veut pas de l'opérateur d'affectation généré par le compilateur, notamment pour les classes dont les instances ne doivent pas être copiées (une base de données, un singleton, etc.). Dans ce cas, une bonne pratique est d'en interdire l'utilisation en le déclarant privé et en ne le définissant pas (ie. ne pas écrire son corps). Il en va d'ailleurs de même pour le constructeur par copie, les deux allant généralement de paire.

  3. #3
    Membre confirmé
    Inscrit en
    Juin 2008
    Messages
    140
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 140
    Par défaut
    Ok, merci de l'information pour l'opérateur d'affectation.
    Par contre pour le problème de destructeur ?

  4. #4
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Citation Envoyé par MicBeastKiller Voir le message
    Par ailleurs, cela ne pose aucun problème lors de la destruction de "theTest2" de détruire "m_nbr" qui a normalement été détruit lors de la destruction de "theTest1".
    theTest1 et theTest2 ont chacun leur membre m_nbr. Chacun détruit donc le sien.

  5. #5
    Membre confirmé
    Inscrit en
    Juin 2008
    Messages
    140
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 140
    Par défaut
    Citation Envoyé par oodini Voir le message
    theTest1 et theTest2 ont chacun leur membre m_nbr. Chacun détruit donc le sien.
    Il me semble, et c'est ce que l'on voit à l'affichage, qu'après l'affectation, "theTest1" et "theTest2" partagent la même adresse pour "m_nbr". Peut-on donc faire un delete sur une adresse qui a déjà eu un delete ?

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 397
    Par défaut
    Non on ne peut pas, c'est un comportement indéfini.
    Voilà pourquoi dans ton code il est indispensable de soit implémenter l'opérateur = , soit l'interdire.

    PS: Ta fonction membre print() devrait être déclarée const, vu qu'elle ne modifie pas l'objet.
    PPS: Par contre, getPtNbr() ne devrait peut-être pas l'être. Ceci peut être plus approprié:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
        int const * getPtNbr( void ) const
        {
            return( m_nbr );
        }
        int       * getPtNbr( void )
        {
            return( m_nbr );
        }
    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.

  7. #7
    Membre confirmé
    Inscrit en
    Juin 2008
    Messages
    140
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 140
    Par défaut
    Merci beaucoup pour les informations.

  8. #8
    Membre Expert Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Par défaut
    Selon ce que tu veux faire, tu peux peut-être utiliser std::shared_ptr (existe aussi dans boost) :
    - http://www.cplusplus.com/reference/m...?kw=shared_ptr
    - http://en.cppreference.com/w/cpp/memory/shared_ptr
    - http://www.boost.org/doc/libs/1_52_0...shared_ptr.htm

    L'opérateur = par défaut devrait être correct et tu n'as pas besoin de delete car le dernier shared_ptr détruira lui-même l'allocation dynamique.

  9. #9
    Membre confirmé
    Inscrit en
    Juin 2008
    Messages
    140
    Détails du profil
    Informations forums :
    Inscription : Juin 2008
    Messages : 140
    Par défaut
    Ok, merci de l'info.

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

Discussions similaires

  1. Réponses: 2
    Dernier message: 10/02/2014, 10h24
  2. Affecter valeur par defaut si champ vide
    Par uloaccess dans le forum Access
    Réponses: 5
    Dernier message: 09/01/2006, 17h12
  3. Réponses: 9
    Dernier message: 17/04/2004, 16h32

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