IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Problème dans un opérateur d'assignation


Sujet :

C++

  1. #1
    Débutant  
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Points : 217
    Points
    217
    Par défaut Problème dans un opérateur d'assignation
    Bonjour

    Dans le livre de Scott Meyers, Effective C++, il y a un truc bizarre. Dans cette classe (cf Item 16)
    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
    template<class T> // template for classes associating
    class NamedPtr { 
    public:
    NamedPtr(const string& initName, T *initPtr);
    NamedPtr& operator=(const NamedPtr& rhs);
    int get(int );
    private:
    string name;
    T *ptr;
    };
    template<class T>int NamedPtr<T>::get(int o){
    	return this->ptr[o];
    }
    template<class T>
    NamedPtr<T>::NamedPtr(const string& initName, T *initPtr )
    : name(initName), ptr(initPtr)
    {}
     
    template<class T>
    NamedPtr<T>& NamedPtr<T>::operator=(const NamedPtr<T>& rhs)
    {
    if (this == &rhs)
    return *this;
    // assign to all data members
    name = rhs.name; // assign to name
    *ptr = *rhs.ptr;//for ptr, assign what's pointed to, not te pointer itself.
    return *this; 
    }
    Il dit bien qu'il faut assigner l'objet pointé par ptr, pas le pointeur lui-même, dans la définition de l'opérateur =.

    Alors j'ai essayé moi-même sa classe:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    int main(){
    	int *o=new int[2];	int *p=new(int[2]);
    	o[0]=1;o[1]=3; p[0]=10;p[1]=33;
    NamedPtr<int> A("ee",o);
    NamedPtr<int> B("ede",p);
    B=A;
    cout<<B.get(0);
    cout<<B.get(1);
    }
    et on voit bien dans ce cas là, que le renvoie du premier cout est 1, mais le second n'est pas 3, mais 33.
    Ensuite, j'ai supprimé les deux déférences, et j'ai obtenu comme renvoie 0 et 3.

    Je suis perplexe là, car je pense que son intention, c'est bien de faire en sorte que A et B soient égaux. Donc les données membres aussi.

  2. #2
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 533
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 533
    Points : 6 709
    Points
    6 709
    Par défaut
    Bonjour,

    attention il ne faut pas confondre un pointeur vers un int et un vecteur d'int

    NamedPtr manipule des pointeurs, pas des vecteurs, il est donc logique que seul le premier élément du vecteur soit modifié
    Bruno Pagès, auteur de Bouml (freeware), mes tutoriels sur DVP (vieux, non à jour )

    N'oubliez pas de consulter les FAQ UML et les cours et tutoriels UML

  3. #3
    Débutant  
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Points : 217
    Points
    217
    Par défaut
    NamedPtr manipule des pointeurs, pas des vecteurs, il est donc logique que seul le premier élément du vecteur soit modifié
    Je crois savoir d'ou vient mon erreur, c'est que j'ai supposé que cela pointait nécessairement vers un tableau, ce qui n'est pas forcément le cas.

    Je suis d'accord, mais je ne voit pas ce que cela change.
    Dans le cas ou cela pointe uniquement vers un entier, pourquoi est il quand même nécessaire de déférencer l'objet?

    Si on avait voulu modifié un tableau entier, comment aurait-on fait?
    merci

  4. #4
    Membre émérite

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Points : 2 252
    Points
    2 252
    Par défaut
    Citation Envoyé par deubelte Voir le message
    Je crois savoir d'ou vient mon erreur, c'est que j'ai supposé que cela pointait nécessairement vers un tableau, ce qui n'est pas forcément le cas.
    Ça ne doit pas être le cas ! NamedPtr<T> est conçu pour manipuler un pointeur sur un objet de type T, pas un pointeur sur un tableau d'objet de type T. (ou tableau dynamique)

    Si tu veux manipuler des tableaux dynamiques, il y a std::vector. Grossièrement un std::vector<T> possède en interne un pointeur pointant vers un tableau d'objet de type T + un int pour connaitre la taille du tableau. Son opérateur d'affectation parcours le tableau et copie élément par élément.

    Citation Envoyé par deubelte Voir le message
    Dans le cas ou cela pointe uniquement vers un entier, pourquoi est il quand même nécessaire de déférencer l'objet?
    Quel objet ? On déférence des pointeurs, pas des objets.
    Et si tu copies directement le pointeur, alors les deux pointeurs sous-jacents aux NamedPtr pointeront vers le même objet (ici le même int). Comme le destructeur de NamedPtr fait un delete, lorsque les deux NamedPtr seront détruits il y aura un double delete sur le même pointeur -> segfault ou corruption mémoire.

  5. #5
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 533
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 533
    Points : 6 709
    Points
    6 709
    Par défaut
    Citation Envoyé par deubelte Voir le message
    Dans le cas ou cela pointe uniquement vers un entier, pourquoi est il quand même nécessaire de déférencer l'objet?
    je ne comprends pas, il n'est pas necessaire de déréférencé puisque comme vous l'aviez dit le premier entier valait bien 1 (et non 10)

    Citation Envoyé par deubelte Voir le message
    Si on avait voulu modifié un tableau entier, comment aurait-on fait?
    ce qu'il faut c'est que le type sur lequel vous pointez ai un opérateur d'affectation qui fasse ce que vous attendez, vous pouvez donc pas exemple utiliser std::vector
    Bruno Pagès, auteur de Bouml (freeware), mes tutoriels sur DVP (vieux, non à jour )

    N'oubliez pas de consulter les FAQ UML et les cours et tutoriels UML

  6. #6
    Débutant  
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Points : 217
    Points
    217
    Par défaut
    Et si tu copies directement le pointeur, alors les deux pointeurs sous-jacents aux NamedPtr pointeront vers le même objet (ici le même int). Comme le destructeur de NamedPtr fait un delete, lorsque les deux NamedPtr seront détruits il y aura un double delete sur le même pointeur -> segfault ou corruption mémoire.
    Ok, j'ai compris. C'est exactement le même problème qui arrive lorsque l'on ne met pas les constructeurs par copie.

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

Discussions similaires

  1. [2.x] Probléme avec un opérateur de comparasion dans Twig
    Par bilbi dans le forum Symfony
    Réponses: 5
    Dernier message: 22/06/2012, 11h08
  2. problème dans l'hebergement
    Par Redouane dans le forum ASP
    Réponses: 9
    Dernier message: 31/12/2003, 23h34
  3. Quel est le problème dans ce code ?
    Par Luther13 dans le forum C
    Réponses: 12
    Dernier message: 26/08/2003, 16h09
  4. Problème dans analisys Manager
    Par ien_ien23 dans le forum MS SQL Server
    Réponses: 7
    Dernier message: 11/07/2003, 14h38
  5. Problème dans requête avec count()
    Par BadFox dans le forum Requêtes
    Réponses: 3
    Dernier message: 08/07/2003, 18h02

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