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 :

fonction operator, valeur de retour


Sujet :

C++

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2002
    Messages
    121
    Détails du profil
    Informations personnelles :
    Âge : 52
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2002
    Messages : 121
    Par défaut fonction operator, valeur de retour
    Bonjour. J'essai de me former au c++ .
    Sur l'exemple suivant , j'ai été obligé de supprimer l'instruction delete name car il semble que je passe deux fois dans le destructeur pour le même objet.Je ne vois pas mon erreur.
    A la base, j'ai écrit cela car je me demandais ce qui se passait à la suite du return dans la fonction test::operator+ . Il semblerait que le constructeur par recopie est utilisée pour copier les valeurs contenu dans l'objet retourné.
    Est ce cela ?C'est bizrre car l'objet est pourtant déjà construit !
    Tout cela n'est vraiment pas clair pour moi, si quelqu'un pouvait m'apporter la lumière ...

    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
    #include "stdafx.h"
    #include <iostream.h>
    #include <string.h>
     
    class test
    {
    int x;
    char * name;
    int num;
    static int cpt;
    public:
    //constructeurs
     test(int c1=0,char * c2 ="?");
    	test(test &);
    	test operator + (test &);
        void showName();
     
    	//destructeurs
    	~test()
    	{
    		cout<<"destructeur";
    		showName();
    		//delete name;
     
    	}
    };
     
    test::test(int c1,char * c2)
    {
    	 int len;
    	 len =strlen(c2);
     
    	 name=new char[len+1];
    	 strcpy(name,c2);
     
    	 x=c1;
    	cout <<"constructeur par defaut";
    	showName();
    }
     
    test::test(test & obj)
    {
     
    int len;
    len=strlen(obj.name + strlen("copie "));
    name=new char[len +1];
    strcpy(name,"copie ");
    strcat(name,obj.name);
     
    	cout <<"constructeur par recopie";
    	showName();
      x= obj.x;
    }
     
    test test::operator+(test & obj)
    { 
     test tmp;
     tmp.x= x+ obj.x;
     cout <<"avant return\n";
     return tmp;
    }
     
     
     
     
    void test::showName()
    {
    	unsigned int i;
    	cout<<"  ";   
    	for (i=0;i<strlen(name);i++)
    	{
          cout<<name[i];   
    	}
    	      cout<<"\n";   
     
    }
    int main(int argc, char* argv[])
    {
     test a=test (5,"a");
     test b(10,"b");
     test c(20,"c");
     cout<<"avant adition\n";
     c=b + c;
     cout<<"après adition\n";
     
    return 0;
    }

    [Balises CODE rajoutées par Loulou24, merci d'y penser à l'avenir]

  2. #2
    Membre averti
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    24
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 24
    Par défaut
    c=b + c; => c'est l'operateur = qui est appelé dans ce cas me semble-t-il, le tiens n'est pas surchargé ... par conséquent le buffer n'est pas copié, sauf son pointeur l'est. A la destruction de l'objet temporaire (a+b), le buffer est dértuit, puis le meme buffer est détruit lorsque c est dértuit.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2002
    Messages
    121
    Détails du profil
    Informations personnelles :
    Âge : 52
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2002
    Messages : 121
    Par défaut
    Ce que tu dis semble logique.
    Je vais essayer d'ajouter une fonction operator =

  4. #4
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 296
    Par défaut
    C'est une erreur typique dû effectivement au fait que tu voudrais que ta classe ait une sémantique de copie alors qu'elle gère des ressources. Il te faut donc définir l'opérateur d'affectation et le constructeur de copie.

    Ensuite, en vrac :

    Je suis étonné que ceci compile
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    test(int c1=0,char * c2 ="?");
    Avec un compilateur conforme, le second paramètre devra obligatoire être const. Preuve rapide : imagine que tu ne donnes qu'un seul argument à l'appel ta fonction et que tu écrives dedans : c2[0]='a';.

    Une signature correcte pour ton opérateur + devrait être au choix :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    test test::operator+(test const & obj) const {...}
    test operator+(test const & lhs, test const & lsh) {...}
    <iostream.h> => <iostream>
    <string.h> => <cstring>
    Trouve une doc à jour. Vu que tu as l'air d'apprendre le C++, pourquoi apprendre un C++ qui va de moins en moins être supporté par les compilateurs ?

    Ton constructeur de copie fuit.

    Enfin, si tu avais utilisé le type std::string plutôt que des char*, tu n'aurais pas eu ton erreur ni besoin d'écrire les opérations de copie. Le temps que tu assimiles les bases du langage, je te conseille de profiter de ce type.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2002
    Messages
    121
    Détails du profil
    Informations personnelles :
    Âge : 52
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2002
    Messages : 121
    Par défaut
    Salut.Merci pour ton aide
    Le compilateur que j'utilise est visual c++ 6 (j'ai pris le premier que j'ai trouvé)
    Lequel me conseillerais tu ? (Autoformation= pas trop de moyens)

    J'ai essayé de surcharger l'operator = , mais j'ai tjrs le mêm pb (si j'essai de faire un delete dans le destructeur, j'ai un plantage)
    voici ma version de la fonction operator =
    test & test::operator = (test & obj)
    {
    int len;
    len=strlen(obj.name) + strlen("op= ");
    delete name;
    name = new char[len+1];
    cout << "fonction operator =\n";
    strcpy(name,"op= ");
    strcat(name,obj.name);
    x=obj.x;
    return *this;

    }

    Je vais regarder str::string, mais poour des raisons didactiques, j'aimerais bien résoudre mon pb.

    A+

  6. #6
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 296
    Par défaut
    Bon ordre des choses :
    1- On duplique
    2- On libère si la duplication est correcte.

    Voilà l'approche (idiome) qui tend à se démocratiser -- dans un programme type où il n'y a pas besoin de tes traces -- lorsque l'on est à un bas niveau et que l'on manipule des ressources (p.ex. des pointeurs) brutes.
    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
    test::test(test const & rhs)
    : x_(rhs.x_)
    , name_(new char[strlen(rhs.name_) + 1])
    {
        strcpy(name_, rhs.name_);
    }
     
    test & test::operator=(test const & rhs) 
    {
        test tmp(rhs);
        swap(rhs);
        return *this;
    }
     
    void test::swap(test & other)
    {
        std::swap(x_, other.x_);
        std::swap(name_, other.name_);
    }
    ou si tu veux décortiquer ton opérateur= pour y rajouter des traces :
    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
    #include <new> // à cause de VC++ 6 IIRC
    test & test::operator= (test const & rhs) 
    {
        const char str[] = "op= ";
        // sizeof(str) == strlen(str)+1 ; mais c'est connu à la compilation
        int len = strlen(rhs.name_) + sizeof(str); 
        char * new_name = new char[len];
        strcpy(new_name, "op= "); 
        strcat(new_name, rhs.name_);
        // ou plus optimisé :
        // -> strcpy(new_name + sizeof(str)-1, rhs.name_);
     
        delete [] name_;
        name_ = new_name;
        cout << "fonction operator =\n"; 
        x_=obj.x_; 
        return *this; 
    }
    Note :
    - l'utilisation de const
    - le +1 pour le 0 terminal des chaines
    - l'ordre des opérations.
    - les crochets sur le delete ; pour garder l'équilibre vu qu'il y en avait sur le new
    - pas de test d'auto-affectation. Ce code est robuste et n'e a pas besoin.
    - pas de déclaration sans initialisation
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  7. #7
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2002
    Messages
    121
    Détails du profil
    Informations personnelles :
    Âge : 52
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2002
    Messages : 121
    Par défaut
    Je n'ai pas trouvé comment utiliser std::swp le compilo me jette.
    (J'ai essayé unsing namespace std, mais il connait pas)

    J'ai essayé de corrigé mon constructeur par copie, mais j'ai toujours un plantage à cause du destructeur.
    Pourrais tu me dire ce qui ne va pas dans mon code :
    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 "stdafx.h"
    #include <iostream.h>
    #include <string.h>
     
    class test
    {
     int x;
     char * name;
      public:
     test(int c1=0, const char * c2 ="?");
     test(const test &);
     test operator + (const test &)const;
     test & operator = (test &);
     ~test()
     {
       //ne plante pas si j'enlève cette instruction !!!
    	 delete []name;
     
     }
    };
     
    test::test(int c1,const char * c2)
    {
     int len;
     len =strlen(c2);
     name=new char[len+1];
     strcpy(name,c2);
     x=c1;
    }
     
     
    test::test(const test & obj)
    {
     int len;
     len=strlen(obj.name + strlen("copie "));
     name=new char[len +1];
     strcpy(name,"copie ");
     strcat(name,obj.name);
     x= obj.x;
     
    }
     
    test test::operator+(const test & obj)const
    { 
     test tmp;
     tmp.x= x+ obj.x;
     return tmp;
    }
     
     
    test & test::operator = (test & obj)
    {
     int len;
     len=sizeof(obj.name) + strlen("op= ");
     name = new char[len];  
     delete [] name;
     strcpy(name,"op= ");
     strcat(name,obj.name);
     x=obj.x;
     return *this; 
    }
     
     
     
    int main(int argc, char* argv[])
    {
     test a=test (5,"a");
     test b(10,"b");
     test c(20,"c");
     c=b + c;
     return 0;
    }

  8. #8
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 296
    Par défaut
    Prenons les bonnes habitudes tant que tu débutes
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    #include <iostream> // pas de .h
    #include <cstring> // pas string.h
    #include <algorithm>
    http://www.dinkumware.com/manuals/re...rith.html#swap ; passer la pub.

    Ensuite :
    - (peu important) En C++, on évite déclarer une variable sans l'initialiser et avant d'en avoir besoin. => "int len = strlen(toto);" et pas "int len; len = strlen(toto)".
    - (pas important ici) c++ != Java. Les listes d'initialisation sont préférables aux inits dans le corps des constructeurs.
    - (critique, faux) ça : "strlen(obj.name + strlen("copie ")); " C'est faux. Regarde bien tes parenthèses
    - (4e dimension, 99.99% de chances que cela soit faux) op+ : si la chaine de tmp n'est pas initialisée, autant renvoyer un entier. C'est bien plus simple et bien moins dangereux.
    - (capital, faux) op=() : relis les deux que je t'avais donné en exemple. Prend un papier (à petits carraux) un stylo et fait des dessins pour chacune des opérations de ta version de l'opérateur= et de la mienne (prend la seconde pour commencer). Il n'y a rien qui te choque ? BTW, tu as oublié le const.
    - (critique, faux) Attention!! strlen(tab) != sizeof(tab) car strlen(tab) + 1 == sizeof(tab)
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  9. #9
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2002
    Messages
    121
    Détails du profil
    Informations personnelles :
    Âge : 52
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2002
    Messages : 121
    Par défaut
    - (peu important) En C++, on évite déclarer une variable sans l'initialiser et avant d'en avoir besoin. => "int len = strlen(toto);" et pas "int len; len
    = strlen(toto)".
    OK

    - (pas important ici) c++ != Java. Les listes d'initialisation sont préférables aux inits dans le corps des constructeurs.
    OK
    (je bosse sur le livre d'exercices de Delannoy, il n'utilise jamais de liste d'initialisation, alors j'ai pris l'habitude)

    - (critique, faux) ça : "strlen(obj.name + strlen("copie ")); " C'est faux. Regarde bien tes parenthèses
    oh putain, la honte !

    - (4e dimension, 99.99% de chances que cela soit faux) op+ : si la chaine de tmp n'est pas initialisée, autant renvoyer un entier. C'est bien plus simple et bien moins dangereux.

    Il me semblait que le constructeur par défaut est utilisé, et donc la chaine est initialisée. non ?


    - (capital, faux) op=() : relis les deux que je t'avais donné en exemple. Prend un papier (à petits carraux) un stylo et fait des dessins pour chacune des opérations de ta version de l'opérateur= et de la mienne (prend la seconde pour commencer). Il n'y a rien qui te choque ? BTW, tu as oublié le const.
    Je ne comprend pas ta version de op=(), tu créés un objet tmp que tu n'utilises pas.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    test & test::operator=(test const & rhs) 
    { 
        test tmp(rhs); 
        swap(rhs); 
        return *this; 
    }
    J'esserais l'utilisation de la fonction std::swap, mais j'aimerais bien le faire au moins une fois sans, cela me semble formateur

    - (critique, faux) Attention!! strlen(tab) != sizeof(tab) car strlen(tab) + 1 == sizeof(tab)
    J'ai utilisé un coup strlen un coup sizeof, ce n'est pas très adroit, mais je ne crois pas avoir fait d'erreur sur ce point ??

  10. #10
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 296
    Par défaut
    Citation Envoyé par butch
    - (4e dimension, 99.99% de chances que cela soit faux) op+ : si la chaine de tmp n'est pas initialisée, autant renvoyer un entier. C'est bien plus simple et bien moins dangereux.
    Il me semblait que le constructeur par défaut est utilisé, et donc la chaine est initialisée. non ?
    Il est effectivement initialisé à un truc "indéfini" (à "?").
    Mais n'est-il pas bizarre que name change quand tu écris:
    ?
    (j'espère que c'est un exo car un opérateur de ce style n'a strictement aucun sens)

    - (capital, faux) op=() : relis les deux que je t'avais donné en exemple. Prend un papier (à petits carraux) un stylo et fait des dessins pour chacune des opérations de ta version de l'opérateur= et de la mienne (prend la seconde pour commencer). Il n'y a rien qui te choque ? BTW, tu as oublié le const.
    Je ne comprend pas ta version de op=(), tu créés un objet tmp que tu n'utilises pas.
    Arf. Honte à moi (heureusement que j'ai des squelettes pour me générer ce genre de choses). Il fallait lire :
    Bref. Mais ce n'est pas cette version de la fonction avec laquelle il faudrait que tu compares la tienne.

    J'aisserais l'utilisation de la fonction std::swap, mais j'aimerais bien le faire au moins une fois sans, cela me semble formateur
    J'ai déjà donné la solution (2e version de op=). Mais honnêtement, il y a plus important à comprendre au début que la manipulation des buffers. Là tu commences et tu risques de prendre l'habitude d'écrire du code faux. L'écriture correcte n'est pas exceptionnelement compliquée, mais le pourquoi-elle-est-correcte demande de comprendre des choses qui ne devraient pas être vues tout de suite.
    Il est plus propre AMHA de commencer par écire des trucs justes et simples (std::string), apprendre à manipuler la mémoire ensuite et comprendre peu après à quel point l'écriture simple-et-juste remplissait parfaitement ses tâches.

    - (critique, faux) Attention!! strlen(tab) != sizeof(tab) car strlen(tab) + 1 == sizeof(tab)
    J'ai utilisé un coup strlen un coup sizeof, ce n'est pas très adroit, mais je ne crois pas avoir fait d'erreur sur ce point ??
    Tu les as utilisé à l'envers (et je n'avais pas fait attention; j'avais cru voir deux strlen).
    - sizeof(pointeur) == généralement sizeof(int) == 4 sur nos PC.
    - sizeof(tableau) == nombre d'éléments du tableau * taille des élements.
    Or name est un pointeur (sur char) et "toto" (et str) est un tableau.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  11. #11
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2002
    Messages
    121
    Détails du profil
    Informations personnelles :
    Âge : 52
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2002
    Messages : 121
    Par défaut
    Bon ben ça marche maintenant.
    Je te rassure, il s'agissait bien d'un exercice.
    J'ai du enlever les sizeof car sizeof de name ne renvoie pas la taille de la chaine, mais la taille du pointeur (name est déclaré char * name).

    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
     
    // test5.cpp : Defines the entry point for the console application.
    //
     
    #include "stdafx.h"
    #include <iostream.h>
    #include <string.h>
     
    #define  DEBUG
    class test
    {
    int x;
    char * name;
    public:
    //constructeurs
    	test(int c1=0, const char * c2="?");
    	test(const test &);
    	test operator + (const test &);
     
    //Comment faire un operateur + qui renvoie un objet de type test ??
    	test & operator = (test &);
        void showName();
        void swap(test & );
     
    	//destructeurs
    	~test()
    	{
    		cout<<"destructeur";
    		showName();
    		delete name;
    	}
    };
     
    test::test(int c1,const char * c2)
    {
     name=new char[strlen(c2)+1];
     
     strcpy(name, c2);
     
     x=c1;
    #ifdef DEBUG
     cout <<"constructeur par defaut" ;
    #endif
     showName();
    }
     
     
    test::test(const test & obj)
    {
     int len;
     len=strlen(obj.name) + strlen("copie ");
     name=new char[len +1];
     strcpy(name,"copie ");
     strcat(name,obj.name);
    #ifdef DEBUG
     cout <<"constructeur par recopie";
     showName();
    #endif
      x= obj.x;
     
    }
     
    test test::operator+(const test & obj)
    { 
      test tmp;
      tmp.x=x+ obj.x;
      return tmp;
    }
     
     
     
    test & test::operator = (test & obj)
    {
     int len;
     cout << "sizeof" << sizeof(obj.name) << " strlen" << strlen(obj.name) <<"\n";
     
     len=strlen(obj.name) + strlen("op= ");
     delete [] name;
      name = new char[len+1];  
    #ifdef DEBUG 
     cout << "fonction operator =\n";
    #endif
     strcpy(name,"op= ");
     strcat(name,obj.name);
     x=obj.x;
     return *this; 
    }
     
     
     
    void test::showName()
    {
    cout <<" nom : " <<  name << endl;
    }
     
    int main(int argc, char* argv[])
    {
     
     test a=test (5,"a");
     test b(10,"b");
     test c(20,"c");
     test somme(10,"somme");
     c=a;
    #ifdef DEBUG
     cout<<"avant adition\n";
    #endif
     somme = c + a;
    #ifdef DEBUG
     cout<<"après adition\n";
    #endif
     
     return 0;
    }

  12. #12
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 296
    Par défaut
    Citation Envoyé par butch
    J'ai du enlever les sizeof car sizeof de name ne renvoie pas la taille de la chaine, mais la taille du pointeur (name est déclaré char * name).
    Oui, c'est ce que j'ai dit, et je n'avais pas dit que ça.

    Reste l'erreur (signalée dans le passé) que tu détruis avant de construire. Ca ne fait pas de dégats dans un code aussi petit qui ne sera jamais véritablement utilisé. Cela peut en faire (à cause de la loi de Murphy) dans un vrai code.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  13. #13
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2002
    Messages
    121
    Détails du profil
    Informations personnelles :
    Âge : 52
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2002
    Messages : 121
    Par défaut
    Ha oui, pardon je viens de relire tes posts et tu m'avais fait remarqué pour sizeof.

    Par contre je ne vois pas de quoi tu parle quand tu dis que je détruis avant de construire.
    je fais cela dans l'operateur d'affectation, mais j'ais vu cela dans les deux livres sur lesquels je bosse

  14. #14
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 296
    Par défaut
    Brule les.

    Dans un monde idéal, les programmeurs ecrivent des opérations atomiques. Si l'opération ne peut être réalisée, alors elle ne doit en aucun cas modifier l'état du système.
    Ici, si l'allocation échoue, tu as déjà modifié ton système en libérant une mémoire qui n'est plus récupérable. C'est mal.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  15. #15
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2002
    Messages
    121
    Détails du profil
    Informations personnelles :
    Âge : 52
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2002
    Messages : 121
    Par défaut
    Je n'avais pas pensé à ça.
    Mais puisque je viens juste de libérer la mémoire avant l'allocation, j'ai peu de chance que l'allocation se passe mal non ?

    Dans la solution que tu me proposes, de créer un objet temporaire, il y a plus de chance pour qu'il y ait un pb d'allocation au moment de la création de l'objet temporaire non ?

    PS: Je ne cherche pas à remettre en cause ton savoir, au contraire, je suis très content d'avoir un interlocuteur à qui je peux poser des questions.

  16. #16
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Mais puisque je viens juste de libérer la mémoire avant l'allocation, j'ai peu de chance que l'allocation se passe mal non ?
    Les erreurs d'allocations dûes à un manque de mémoire sont très rare, mais il ne faut pas oublier qu'un constructeur peut lancer une exception et peut donc également faire échouer l'allocation, ce qui arrive déjà plus souvent.

    Dans la solution que tu me proposes, de créer un objet temporaire, il y a plus de chance pour qu'il y ait un pb d'allocation au moment de la création de l'objet temporaire non ?
    Il y en a tout autant, mais au moins si cela arrive, notre objet sera toujours valide car il son buffer interne n'aura pas été détruit, et l'execution du programme pourra continuer normalement.

  17. #17
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 296
    Par défaut
    1- Tout à fait. Mais la loi de Murphy n'est jamais avec nous. Et sur un vrai produit, si la situation qui ne devait jamais se produire finit par se produire et plante le programme, cela ne fait jamais sérieux.
    Mais ... as-tu libéré assez de mémoire ?

    2- Et combien même. On ne ferait que rapprocher le moment de l'épuisement de mémoire de 4 octets. Ce n'est rien du tout.
    Mais ce n'est pas le cas, mais un chouilla différent, car le temporaire est dans la pile et non dansle freestore.
    Sans passer par le temporaire (qui règle plusieurs choses proprement), il y a la seconde solution que j'avais donnée.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  18. #18
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2002
    Messages
    121
    Détails du profil
    Informations personnelles :
    Âge : 52
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2002
    Messages : 121
    Par défaut
    Salut.
    Ma curiosité étant sans fin, je continue à te poser des questions.

    Dans mon bouquin, ils parlent de 4 zones pour la mémoire.
    Le segment de code, la pile, le tas et ils ne disent pas quelle est le quatrième ?

    Ce que tu appelles le freestore, c'est le tas ?

    Lorsque tu mes un objet temporaire sur la pile, il ne peut pas y avoir un problème d'insuffisance de mémoire non plus ?
    Cet emplacement est prévu dès la compile ?

  19. #19
    Expert confirmé
    Avatar de Luc Hermitte
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2003
    Messages
    5 296
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Août 2003
    Messages : 5 296
    Par défaut
    Moi, j'ai 5 zones mémoire en C++:
    - les données constantes (divers trucs connus à la compilation)
    - la pile dans laquelle se trouvent les données automatiques. Ces dernières sont construites au point de définition et automatiquement libérées à la fin de leur portée
    - le free store : une des deux zones pour la "mémoire dynamique". allocations et désallocations se font par new et delete
    - le tas : l'autre zone. Cette fois, on passe par la famille de malloc et free
    - Globale/Statique : pour les données globales ou statiques. Mémoire réservée dès le début, objets pas forcément construits à l'initialisation du programme, libérations et destructions à la fin du programme.

    Le tas et le free store peuvent être liés, mais ce n'est absolument pas nécessaire.

    Les problèmes d'insuffisance de mémoire sur la pile sont différents de ceux dans les zones "dynamiques". La pile est généralement (/toujours ?) plus réduite. Mais si le freestore venait à être épuisé, cela ne voudrait pas dire que la pile le serait également.
    NB: il est évident qu'un énorme truc qui ne trouverait pas sa place sur le free store ne la trouverait pas dans la pile. D'un autre côté on ne stocke pas les mêmes choses dans ces deux zones. Genre on me mettra pas 42000 doubles sur la pile.
    Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
    Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...

  20. #20
    Membre confirmé
    Profil pro
    Inscrit en
    Avril 2002
    Messages
    121
    Détails du profil
    Informations personnelles :
    Âge : 52
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Avril 2002
    Messages : 121
    Par défaut
    Dans le cas ou tu essais de construire un objet sur la pile et qu'il n'y a plus de place, que se passe t il ? Un plantage du programme ?

    Avec les allocations dynamiques, on peut savoir si l'allocation s'est bien passé en testant le pointeur renvoyé, mais lors de la création d'un objet sur la pile,peut on tester si la création s'est bien passé . Voir même peut on avant la construction tester qu'il y aura assez de place sur la pile ?

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. fonction avec valeur de retour
    Par kawther dans le forum Interfaces Graphiques
    Réponses: 1
    Dernier message: 03/07/2009, 10h51
  2. [Tableaux] fonction et valeur de retour : mal codée ?
    Par Dsphinx dans le forum Langage
    Réponses: 6
    Dernier message: 22/06/2007, 14h12
  3. Réponses: 2
    Dernier message: 11/05/2006, 18h41
  4. valeur de retour de la fonction "system" en C
    Par benhoeil dans le forum C
    Réponses: 14
    Dernier message: 16/09/2005, 11h30
  5. Pourquoi une seule valeur de retour pour les fonctions ?
    Par Bruno75 dans le forum Langages de programmation
    Réponses: 33
    Dernier message: 18/01/2004, 13h58

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