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 :

Plus d'appel au destructeur qu'au constructeur ?


Sujet :

C++

  1. #1
    Membre du Club
    Homme Profil pro
    Inscrit en
    Juin 2008
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 56
    Points : 50
    Points
    50
    Par défaut Plus d'appel au destructeur qu'au constructeur ?
    Le C++ c'est chaud...

    J'ai un petit programme que j'ai essayé de simplifier au maximum
    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
    using namespace std;
    #include <string>
    #include <vector>
    #include <stdio.h>
     
    class ebovar
    {
    public:
          union {
              int i;
              float f;
              bool b;
              string *s;
              void *o;
          };
     
    // var is null
    	ebovar() : i(0) {
    		printf("++ create NULL\n");
    	}
    	~ebovar()
    	{
    		printf("-- delete ebovar %d\n", i);
    	}
     
    // integer function
    	ebovar(int v) {
    		i = v;
    		printf("++ create int %d\n", i);
    	}
    	operator int() { return i; }
    };
     
    /********************************************************************
    **
    ** Operateur +
    **
    ********************************************************************/
     
    ebovar operator+(ebovar left_op, ebovar right_op)
    {
    	return (ebovar)((int)left_op + (int)right_op);
    }
     
    int main(int _argc, char **_argv)
    {
    	ebovar _a = 10;
    	ebovar _b = 12;
    	ebovar _result = _b + _a;
    }
    il affiche
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    ++ create int 10
    ++ create int 12
    ++ create int 22
    -- delete ebovar 12
    -- delete ebovar 10
    -- delete ebovar 22
    -- delete ebovar 12
    -- delete ebovar 10
    Comment puis-je avoir 3 appels au constructeur de ma classe et 5 appels au destructeur ?
    Qu'est ce que j'ai manqué ?

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

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

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Points : 2 160
    Points
    2 160
    Par défaut
    Bonjour

    C'est à cause des copies des paramètres par l'opérateur + :
    Citation Envoyé par webshaker Voir le message
    ebovar operator+(ebovar left_op, ebovar right_op)
    Tu n'as pas l'affichage des créations car tu n'as pas écrit le constructeur par copie de ta classe (le compilateur l'a fait pour toi).

  3. #3
    Membre du Club
    Homme Profil pro
    Inscrit en
    Juin 2008
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 56
    Points : 50
    Points
    50
    Par défaut
    Ah ouais!!!

    comme ce sont des classes j'ai remplacer par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ebovar operator+(ebovar &left_op, ebovar &right_op)
    Ca ne pourra qu'alle plus vite !
    Merci.

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

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

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Points : 2 160
    Points
    2 160
    Par défaut
    Pas besoin de pouvoir modifier les opérandes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    ebovar operator+(ebovar const & left_op, ebovar const & right_op)
    Il faudra corriger l'opérateur de conversion en entier de ta classe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int operator int() const { return i; }
    Citation Envoyé par webshaker Voir le message
    Ca ne pourra qu'alle plus vite !
    Pour les types qui font la taille des types primitifs, ça ne va pas plus vite.
    Les deux codes (ebovar operator+(ebovar const & left_op, ebovar const & right_op) et ebovar operator+(ebovar const left_op, ebovar const right_op)) sont acceptables ici.

  5. #5
    Membre du Club
    Homme Profil pro
    Inscrit en
    Juin 2008
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 56
    Points : 50
    Points
    50
    Par défaut
    Merci.

    Tu peux vaguement m'expliquer à quoi sert le const ?
    Si je le met, il ne m'est plus possible d'utiliser d'appeler les méthode de l'object dans la fonction qui surcharge le +

    Ca me dit
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    error: passing 'const ebovar' as 'this' argument of 'float ebovar::getFloat()' discards qualifiers
    Ca change quoi de ne pas le mettre ?

  6. #6
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    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 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par Ehonn Voir le message
    Les deux codes (ebovar operator+(ebovar const & left_op, ebovar const & right_op) et ebovar operator+(ebovar const left_op, ebovar const right_op)) sont acceptables ici.
    Sauf que faire un passage par copie constante n'a aucun intérêt. Donc ebovar operator+(ebovar const left_op, ebovar const right_op) est à oublier.
    Et je vois pas pour quelle raison tu crois ça acceptable ?
    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.

  7. #7
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    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 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Les fonctions d'une classes (aussi appelées méthodes) sont liées à une variable automatique, this, qui est un pointeur vers l'objet sur lequel la fonction est appelée.
    Ainsi, si f est un ebovar, f.getFloat()provoque l'appel de la fonction ebovar::getFloat() avec this=&f.

    Or, il n'est pas possible de prendre un pointeur modifiant sur une valeur constante.
    Il faut donc un moyen de définir this non pas comme un ebovar* mais comme un ebovar const*.
    L'astuce, c'est de placer un const sur la fonction elle-même.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class ebovar {
    //je passe les détails...
    public:
        //déclaration
        float getFloat() const;
    
        //déclaration en place
        float getFloat() const {/* ... */}
    };
    
    //définition en dehors d'une fonction membre.
    float ebovar::getFloat() const {/* ... */}
    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

  8. #8
    Membre du Club
    Homme Profil pro
    Inscrit en
    Juin 2008
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 56
    Points : 50
    Points
    50
    Par défaut
    Bon...
    A chaque nouvelle ligne de code un nouveau problème ;(
    J'ai donc solutionné mon problème de constructeur et destructeur en passant tout par référence.

    Maintenant je veux ajouter une nouvelle surcharge pour pouvoir ajouter un int à un ebovar.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    ebovar operator+(ebovar &left_op, int ivalue)
    {
    	return (ebovar)(left_op.i + ivalue);
    }
    Et ça fonctionne !!!

    Donc je decide de gérer un nouveau type de variable puisque mon ebovar est sensé être un variant.
    j'ajoute donc le code suivant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    	ebovar(float v) {
    		f = v;
    		var_type = EBO_FLOAT;
    		printf("++ create int %d\n", i);
    	}
    	operator float() { return f; }
    Et là, ca marche à moitié seulement.
    ebovar _result = _a + _b; ça compile et ça marche
    ebovar _result = _a + 8; ça compile et ça marche
    par contre ebovar _result = _a + _b + 8; ça ne compile pas du tout.

    C'est chaud non ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    test.cpp: In function 'int main(int, char**)':
    test.cpp:78: error: ambiguous overload for 'operator+' in 'operator+(ebovar&, ebovar&)(((ebovar&)(& _b))) + 8'
    test.cpp:78: note: candidates are: operator+(int, int) <built-in>
    test.cpp:78: note:                 operator+(float, int) <built-in>
    Le code complet est là.

    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
    using namespace std;
    #include <string>
    #include <map>
    #include <stdio.h>
     
    #define EBO_INT				0
    #define EBO_FLOAT				1
    #define EBO_STRING			2
    #define EBO_ERROR				3										// Operation fire error
    #define EBO_BOOL				EBO_INT + 4							// BOOL is a specif INT
    #define EBO_NULL				EBO_INT + 8							// NULL is a specif INT 
    #define EBO_ARRAY				EBO_ERROR +	32
    #define EBO_OBJECT			EBO_ERROR + 64
     
    class ebovar
    {
    public:
    	int var_type;
    	union {
    		int i;
    		float f;
    		bool b;
    		string *s;
    		map<ebovar, ebovar> *m;
    		void *o;
    	};
     
    // var is null
    	ebovar() {
    		i = 0;
    		var_type = EBO_NULL;
    		printf("++ create NULL\n");
    	}
    	~ebovar()
    	{
    		printf("-- delete ebovar %d\n", i);
    		i = 1;
    		return;
    	}
     
    // integer function
    	ebovar(int v) {
    		i = v;
    		var_type = EBO_INT;
    		printf("++ create int %d\n", i);
    	}
    	operator int() { return i; }
     
    // float function
    	ebovar(float v) {
    		f = v;
    		var_type = EBO_FLOAT;
    		printf("++ create float %d\n", i);
    	}
    	operator float() { return f; }
    };
     
    /********************************************************************
    **
    ** Operateur +
    **
    ********************************************************************/
     
    ebovar operator+(ebovar &left_op, ebovar &right_op)
    {
    	return (ebovar)(left_op.i + right_op.i);
    }
     
    ebovar operator+(ebovar &left_op, int ivalue)
    {
    	return (ebovar)(left_op.i + ivalue);
    }
     
    int main(int _argc, char **_argv)
    {
    	ebovar _a = 10;
    	ebovar _b = 12;
    	ebovar _result = _a + _b + 8;
    }

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

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

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Points : 2 160
    Points
    2 160
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Sauf que faire un passage par copie constante n'a aucun intérêt. Donc ebovar operator+(ebovar const left_op, ebovar const right_op) est à oublier.
    Et je vois pas pour quelle raison tu crois ça acceptable ?
    Le passage par copie constante a un intérêt sémantique (mais pas plus).

    Remplace ton :
    Citation Envoyé par webshaker Voir le message
    operator float() { return f; }
    par :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    float operator float() const { return f; }
    Les const te permettent d'interdire les modifications et donc peuvent permettent d'éviter des erreurs d'étourderies.

  10. #10
    Membre du Club
    Homme Profil pro
    Inscrit en
    Juin 2008
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 56
    Points : 50
    Points
    50
    Par défaut
    Alors un complément d'information utile est que j'ai g++ 4.1
    lequel visiblement ne gère pas le C++11

    du coup
    explicit operator int() { return i; } me renvoit
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    test.cpp:47: error: only declarations of constructors can be 'explicit'
    et
    float operator float() const { return f; } me renvoit
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    test.cpp:55: error: return type specified for 'operator float'
    Je pense que je vais commencer par une mise a jour de g++ !

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

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

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Points : 2 160
    Points
    2 160
    Par défaut
    Vire le type de retour que j'avais mis...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    operator float() const { return f; }

  12. #12
    Membre du Club
    Homme Profil pro
    Inscrit en
    Juin 2008
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 56
    Points : 50
    Points
    50
    Par défaut
    Bon.

    Ca fonctionne en effet, sauf que j'ai pas compris pourquoi.
    Je vais un peu chercher sur Internet, histoire de ne pas griller toutes mes cartouches sur ce forum d'un coup

    Merci en tout cas.

  13. #13
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    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 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par Ehonn Voir le message
    Le passage par copie constante a un intérêt sémantique (mais pas plus).
    Sauf à vouloir gâcher de la mémoire, ça n'a strictement aucun intérêt.
    Si un paramètre est const, il sera const&, s'il est copié, on s'en moque qu'il soit const.
    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.

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

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

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Points : 2 160
    Points
    2 160
    Par défaut
    Depuis quand int const gâche de la mémoire...
    int const est acceptable, ce n'est pas le seul, mais il reste acceptable...

  15. #15
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    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 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Depuis quand on parle de type primitif ?
    Les types primitifs sont passés pas copie, et quand on passe un paramètre par copie, on s'en moque de la constance ou pas, c'est une copie.
    Maintenant va t'amuser à passer par copie une vraie structure/classe, puis éclate-toi à la transférer sur plusieurs niveaux d'appels par copie. Chaque copie est un gachis de mémoire pur et dur, et la constance n'a strictement aucun intérêt.
    L'appelant s'en moque, il s'agit d'une copie et donc ce qu'il passe en paramètre n'est pas affecté: c'est tout ce qui l'intéresse.
    Le développeur de la méthode, au mieux s'en moque, au pire est gêné: on lui fournit une copie constante, qu'il ne peut donc pas modifier, et il doit alors refaire sa propre copie pour agir dessus si nécessaire. Intérêt de la copie const : pire que nulle.
    Une signature de fonction c'est un contrat, pas des mot-clés mis bout à bout par hasard. const& assure que l'objet ne sera pas modifié. La copie également puisqu'il sera copié lors du passage. Une copie const apporte strictement aucune information, sauf que le programmeur de la méthode est mauvais, sait pas ce qu'il fait (il a vaguement entendu qu'il fallait passer const les paramètres quand nécessaire), ou a oublié un symbole &.

    Quand un étudiant me montre une copie constante, je le renvois illico. Soit il fait une copie et il assume et il sait le justifier. Soit il fait une const&.

    Citation Envoyé par webshaker Voir le message
    Ca fonctionne en effet, sauf que j'ai pas compris pourquoi.
    Je vais un peu chercher sur Internet, histoire de ne pas griller toutes mes cartouches sur ce forum d'un coup
    Une méthode const assure que le this (l'objet, ses variables internes) n'est pas modifié. Sur un objet const tu ne peux utiliser que des méthodes const.
    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.

  16. #16
    Membre du Club
    Homme Profil pro
    Inscrit en
    Juin 2008
    Messages
    56
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 56
    Points : 50
    Points
    50
    Par défaut
    Merci Bousk,

    J'avais fini par trouver un tuto plutôt bien fait qui explique les effets du const sur la surcharge des opérateurs (entre autre).

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

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

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Points : 2 160
    Points
    2 160
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Depuis quand on parle de type primitif ?
    Depuis le message #4.

    Passer des copies constantes m'a déjà permis d'éviter des erreurs d’inattention (tentative de modification de la mauvaise variable).

  18. #18
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 189
    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 189
    Points : 17 141
    Points
    17 141
    Par défaut
    Pour information, la constance d'un paramètre de fonction n'a pas à être respectée dans l'implémentation.
    Considérons:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int doubler(int const);
     
    int doubler(int a) {
        return 2*a;
    }
    Ces deux fonctions sont la même pour l'édition de lien.
    Du coup, effectivement, pour l'appelant, ca ne change rien.

    Lu sur cppreference.com (partie parameter list):
    The type of each function parameter in the parameter list is determined according to the following rules:
    1) First, decl-specifier-seq and the declarator are combined as in any declaration to determine the type.
    2) If the type is "array of T" or "array of unknown bound of T", it is replaced by the type "pointer to T"
    3) If the type is a function type F, it is replaced by the type "pointer to F"
    4) Top-level cv-qualifiers are dropped from the parameter type (This adjustment only affects the function type, but doesn't modify the property of the parameter: int f(const int p, decltype(p)*); and int f(int, const int*); declare the same function)
    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

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut
    Citation Envoyé par Bousk Voir le message
    Depuis quand on parle de type primitif ?
    Les types primitifs sont passés pas copie, et quand on passe un paramètre par copie, on s'en moque de la constance ou pas, c'est une copie.
    Maintenant va t'amuser à passer par copie une vraie structure/classe, puis éclate-toi à la transférer sur plusieurs niveaux d'appels par copie. Chaque copie est un gachis de mémoire pur et dur, et la constance n'a strictement aucun intérêt.
    L'appelant s'en moque, il s'agit d'une copie et donc ce qu'il passe en paramètre n'est pas affecté: c'est tout ce qui l'intéresse.
    Le développeur de la méthode, au mieux s'en moque, au pire est gêné: on lui fournit une copie constante, qu'il ne peut donc pas modifier, et il doit alors refaire sa propre copie pour agir dessus si nécessaire. Intérêt de la copie const : pire que nulle.
    Une signature de fonction c'est un contrat, pas des mot-clés mis bout à bout par hasard. const& assure que l'objet ne sera pas modifié. La copie également puisqu'il sera copié lors du passage. Une copie const apporte strictement aucune information, sauf que le programmeur de la méthode est mauvais, sait pas ce qu'il fait (il a vaguement entendu qu'il fallait passer const les paramètres quand nécessaire), ou a oublié un symbole &.

    Quand un étudiant me montre une copie constante, je le renvois illico. Soit il fait une copie et il assume et il sait le justifier. Soit il fait une const&.


    Une méthode const assure que le this (l'objet, ses variables internes) n'est pas modifié. Sur un objet const tu ne peux utiliser que des méthodes const.
    Dans l'absolu, tu n'a pas tord : soit on passe une référence constante, soit on passe une copie.

    Mais, à mon sens, c'est le fait de passer un paramètre par copie qui est un gâchis de mémoire et non le fait que cette copie soit constante.

    Car la notion de constante est totalement transversale par rapport à tout le reste : la constance d'une donnée permet juste de préciser un contrat (disons le franchement : un invariant) indiquant ce qui est acceptable ou non pour une donnée particulière et qui se résume en "on peut (ou non) modifier la donnée en question" (et donc n'appeler que des fonctions qui s'engagent à ne pas modifier l'objet en question ... ou plus).

    Je suis donc tout à fait d'accord avec toi : la transmission par copie constante d'un paramètre est très certainement suboptimale, quel que soit le type du paramètre transmis. MAIS il est tout aussi vrai que le fait que la constance répond à une problématique tout autre que le fait de passer le paramètre par copie et qu'il peut donc être parfaitement justifié de passer (du moins conceptuellement parlant) une copie ... constante comme paramètre à une fonction.

    Techniquement parlant, ce sera du gâchis de mémoire, parce qu'il faudra "re-copier" la copie sous une forme non constante si on envisage de la modifier, mais uniquement parce que l'on parle de copie, non parce que l'on parle de constance

    D'ailleurs, si tu y regarde d'un peu plus près, il n'est pas rare de transmettre un paramètre par référence constante à une fonction et de constater que la première chose que le fait à l'intérieur de cette fonction est... d'en créer une copie temporaire que nous pourrons manipuler (et modifier) à notre gré
    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

  20. #20
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    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 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    En même temps, ça fait 3 posts que je le dis qu'une copie c'est un gachis de mémoire. Et que const n'a rien à voir et ne sert à rien. Donc je vois pas comment tu peux comprendre/croire que je lie le const à un gachis de mémoire... sauf à extrapoler quand la copie constante nous force à refaire une copie non constante, ce qui est un double gachis mémoire, mais dont la source est toujours la copie inutile.
    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.

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

Discussions similaires

  1. appeler le destructeur dans une fonction
    Par asoka13 dans le forum C++
    Réponses: 3
    Dernier message: 12/05/2008, 00h24
  2. [POO] Appel des destructeurs
    Par Merfolk dans le forum Langage
    Réponses: 2
    Dernier message: 28/03/2008, 17h59
  3. Réponses: 3
    Dernier message: 31/07/2007, 21h18
  4. [Loufoque] Appel de destructeur
    Par Chii-san dans le forum C++
    Réponses: 12
    Dernier message: 18/05/2006, 10h16

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