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 :

Différence entre delete et delete []


Sujet :

C++

  1. #21
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Tu remarqueras que tes opérateurs delete ne sont pas virtuels, ce qui implique que... leur utilisation ne sera pas polymorphique : tu te trouve dans une situation dans laquelle l'operateur delete de D cache celui de B, pour autant que tu ait la certitude de travailler avec un pointeur sur D.

    !!! si tu appelle delete sur un pointeur sur B qui pointe vers un objet de type D, ce sera l'operateur B::delete qui sera appelé, et non l'opérateur D::delete, avec tous les dangers que cela peut représenter !!!
    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

  2. #22
    Membre émérite
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2011
    Messages
    618
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2011
    Messages : 618
    Par défaut
    Je croyais que l'operator delete ne pouvait être virtuel, m'aurait-on mentis ?

  3. #23
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Tu remarqueras que tes opérateurs delete ne sont pas virtuels, ce qui implique que... leur utilisation ne sera pas polymorphique : tu te trouve dans une situation dans laquelle l'operateur delete de D cache celui de B, pour autant que tu ait la certitude de travailler avec un pointeur sur D.

    !!! si tu appelle delete sur un pointeur sur B qui pointe vers un objet de type D, ce sera l'operateur B::delete qui sera appelé, et non l'opérateur D::delete, avec tous les dangers que cela peut représenter !!!
    Non, non.

    Les opérateurs new et delete d'une classe sont toujours static même s'ils ne sont pas explicitement définis comme tel (de toute façon à quelle instance s'appliquerait un new??). Ils ne peuvent donc être virtuels.

    delete p utilise le type statique de p pour savoir si l'appel est valide et utilise l'opérateur delete du type dynamique de p si le destructeur du type statique est virtuel.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    struct B {
    virtual ˜B();
    void operator delete(void*, size_t);
    };
    struct D : B {
    void operator delete(void*);
    };
    void f()
    {
    B* bp = new D;
    delete bp; //1: uses D::operator delete(void*)
    }
    Sinon, c'est indéterminé
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    struct B {
    ˜B();
    void operator delete(void*, size_t);
    };
    struct D : B {
    void operator delete(void*);
    };
    void f()
    {
    B* bp = new D;
    delete bp; //undefined behaviour
    }
    delete []p sur un type statique et dynamique différent est un comportement indéterminé.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    struct B {
    virtual ˜B();
    void operator delete[](void*, size_t);
    };
    struct D : B {
    void operator delete[](void*, size_t);
    };
    void f(int i)
    {
    D* dp = new D[i];
    delete [] dp; // uses D::operator delete[](void*, size_t)
    B* bp = new D[i];
    delete[] bp; // undefined behavior
    }

  4. #24
    screetch
    Invité(e)
    Par défaut
    pour être précis, delete appelle le destructeur de la classe (dynamique donc) avec un paramètre caché, 1
    ce paramètre dit "libère la mémoire après l'appel"
    le destructeur appelle les destructeurs des classes parentes avec le paramètre 0, puis libère la mémoire avec operator delete qui correspond le mieux (celui de la classe si possible, sinon celui du parent, etc etc)
    comme c'est le destructeur qui libère la mémoire, il appelle toujours le delete correct.


    En gros lorsque tu fais delete a; il se passe:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    push 1
    call vtable(a)->0
    et le destructeur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    ...blablabla destruction
    push 0
    call parentdestructor
    if parametrecaché
      call operator delete

  5. #25
    screetch
    Invité(e)
    Par défaut
    (encore une fois c'est du détail d'imlémentation et on est pas sensé savoir, hein, c'est juste pour expliquer comemnt ca marche et c'est pas par magie)

  6. #26
    Membre éprouvé
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Par défaut
    Merci pour toutes vos réponses, mais ca m'enmèle un peu. Doit on utiliser ou non un tableau sur des objets dynamiques?


    Dans les classes données par Sutter, estce que vous pouver me donner des exemples d'implémentation des delete et des new qui sont déclarés?

    merci

  7. #27
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par screetch Voir le message
    (encore une fois c'est du détail d'imlémentation et on est pas sensé savoir, hein, c'est juste pour expliquer comemnt ca marche et c'est pas par magie)
    Quel compilateur ? Quelle version ?

    Ceci dit, quand tu es codeur C++, c'est undefined behaviour qui est important. Ce que tu décris concerne le développeur de compilateur.

  8. #28
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par deubelte Voir le message
    Merci pour toutes vos réponses, mais ca m'enmèle un peu. Doit on utiliser ou non un tableau sur des objets dynamiques?
    objet dynamique La réponse est : la sémantique de copie est rarement compatible avec la sémantique d'entité qui est souvent celle d'un héritage publique. Alors syntaxiquement, pfff... C'est tout de suite le souk.

    Citation Envoyé par deubelte Voir le message
    Dans les classes données par Sutter, estce que vous pouver me donner des exemples d'implémentation des delete et des new qui sont déclarés?

    merci
    Bonne lecture de la traduction dvp de Penser en C++, 13.5.2. Surcharger new & delete pour une classe de Bruce Eckel

  9. #29
    screetch
    Invité(e)
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Quel compilateur ? Quelle version ?

    Ceci dit, quand tu es codeur C++, c'est undefined behaviour qui est important. Ce que tu décris concerne le développeur de compilateur.
    Oui c'etait juste pour expliquer comment les compilateurs appellent la méthode "delete" correcte en fonction du type dynamique. Ca n'a aucun autre but qu'être éducatif.

    sinon, quel compilo: Visual studio et GCC au moins

  10. #30
    Membre éprouvé
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Par défaut
    La réponse est : la sémantique de copie est rarement compatible avec la sémantique d'entité qui est souvent celle d'un héritage publique. Alors syntaxiquement, pfff... C'est tout de suite le souk.
    .

    C'est quoi la sémantique de copie ?

    C'est quoi la sémantique d'entité?

  11. #31
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par screetch Voir le message
    sinon, quel compilo: Visual studio et GCC au moins
    Ah, OK. C'était pour savoir si tu avais regardé que visual ou d'autres compilo.

  12. #32
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par deubelte Voir le message
    .

    C'est quoi la sémantique de copie ?

    C'est quoi la sémantique d'entité?
    F.A.Q. à partir d'ici et à partir d'ici

    Ou dans une approche connexe : Fonctions virtuelles et L'operateur d'affectation : operator=

  13. #33
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Par défaut
    Citation Envoyé par deubelte Voir le message
    En fait, je me suis posé cette question, car dans le livre de Sutter, exceptionnal C++, page 144, on a:

    Consider the following 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
     
    class B
    {
    virtual ~B();
    void operator delete (void*,size_t) throw();
    void operator[] delete (void*,size_t) throw();
    void f(void*,size_t) throw();
    };
    class D: public B
    {
    public:
    void operator delete (void*)throw();
    void operator delete[] (void*)throw();
    };
    Or, dans le livre de Scott Meyers, il nous dit qu'il ne faut jamais traiter des tableau de manière polymorphe.
    (Never treat array polymorphically). mais dans le code ci-dessus, cela laisse penser qu'on va utiliser des tableaux d'objets dérivés.

    Il y a comme un petit problème, ou du moins, une incohérence dans la question de Sutter.
    As-tu lu la question (et surtout l'explication) jusqu'au bout ?

    Car justement il se sert de ce bout de code pour montrer qu'on ne doit pas traiter polymorphiquement des tableaux (c'est dans la partie 2 de l'item en question). Je cite :

    Citation Envoyé par Exceptional C++ (item 36)
    B* pb2 = new D[10];
    delete[] pb2;

    This is undefined behavior. The language requires that the static type of the pointer that is passed to operator delete[]() must be the same as its dynamic type. For more information on this topic, see also Scott Meyers' section, "Never Treat Arrays Polymorphically" in Meyers99.

    Guideline

    Never treat arrays polymorphically.

    Citation Envoyé par deubelte Voir le message
    Merci pour toutes vos réponses, mais ca m'enmèle un peu. Doit on utiliser ou non un tableau sur des objets dynamiques?
    Non : Never treat arrays polymorphically.

  14. #34
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par gl Voir le message
    Non : Never treat arrays polymorphically.
    Ceci dit cette formulation ne doit pas être lue trop vite. Le problème n'est pas qu'on ne doit pas allouer dynamiquement des objets polymorphes. Ce que dit la phrase est que le tableau dynamique ne doit pas être traité de façon polymorphe, i.e. le pointeur sur le tableau doit avoir type statique et type dynamique qui coïncident.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    struct B {
    virtual ˜B();
    void operator delete[](void*, size_t);
    };
    struct D : B {
    void operator delete[](void*, size_t);
    };
    void f(int i)
    {
    D* dp = new D[i];
    delete [] dp; // uses D::operator delete[](void*, size_t)
    }
    ==> OK dp n'est pas traité de façon polymporphe : le tableau est bien un tableau de D

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void f(int i)
    {
    B* bp = new D[i];
    delete[] bp; // undefined behavior
    }
    ==> KO pp est traité de façon polymporphe : le tableau bp de type B* alors que ce sont des D

  15. #35
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Ceci dit, quand tu es codeur C++, c'est undefined behaviour qui est important. Ce que tu décris concerne le développeur de compilateur.
    Disons qu'il y a certaines personnes qui ont besoin de comprendre la motivation derrière une règle pour comprendre et retenir la règle. Pour ma part, je sais que si j'accepte sans soucis le "c'est comme ça pour des raisons qu'on verra plus tard", j'ai du mal avec le "c'est comme ça parce que c'est comme ça".
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  16. #36
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Ceci dit cette formulation ne doit pas être lue trop vite. Le problème n'est pas qu'on ne doit pas allouer dynamiquement des objets polymorphes. Ce que dit la phrase est que le tableau dynamique ne doit pas être traité de façon polymorphe, i.e. le pointeur sur le tableau doit avoir type statique et type dynamique qui coïncident.
    Effectivement ma réponse était un peu lapidaire[1]. Tu as eu raison de compléter et préciser.


    [1] Je m'étais placé dans le contexte du questionnement initial, et non dans le cadre de la formulation directe de la réponse que j'ai citée. Mon intervention est du coup assez confusante.

  17. #37
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par gl Voir le message
    Effectivement ma réponse était un peu lapidaire. Tu as eu raison de compléter et préciser.
    C'est pas tant ta réponse que la phrase de Sutter qui doit bien être lue en dégustant chaque mot. Le problème avec ces gens là c'est qu'ils pensent qu'on a tous un esprit aussi rapide et affuté qu'eux. Moi, ca me demande souvent de relire plusieurs fois cette pauv' phrase de 4 mots et je suis pas sur d'avoir tout compris

  18. #38
    Membre éprouvé
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Par défaut
    Bonne lecture de la traduction dvp de Penser en C++, 13.5.2. Surcharger new & delete pour une classe de Bruce Eckel
    J'ai lu. C'est un bon exemple d'allocation sur la stack (si j'ai bien compris). On crée une variable statique de la classe, qui sert d'allocation globale, et on alloue au fur et a mesure des objets de cette classe.
    C'est la première fois que je vois un exemple de l'opérateur new qui n'alloue pas sur le tas.

  19. #39
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Citation Envoyé par deubelte Voir le message
    J'ai lu. C'est un bon exemple d'allocation sur la stack (si j'ai bien compris). On crée une variable statique de la classe, qui sert d'allocation globale, et on alloue au fur et a mesure des objets de cette classe.
    C'est la première fois que je vois un exemple de l'opérateur new qui n'alloue pas sur le tas.
    Pas de bol. Ce n'est ni sur la pile, ni sur le tas

    Les variables statiques sont dans des zones dédiées et ne sont donc ni sur la pile ni sur le tas.

    Petite remarque : le C++ en soi ne contient aucune notion de pile, de tas, de zone code, de zone données, etc. Le langage ne parle que de la durée de vie d'une variable. Les notions de pile, de tas, et des zones données ou de code relèvent du cours de système

  20. #40
    Membre éprouvé
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Par défaut
    oK,
    mais pour répondre à la question initiale de l'exo, sur pourquoi size_t est présent dans la déclaration de delete dans B et pas dans D, je dirais que B ne connait à priori pas la taille de l'objet D. Il est donc nécessaire de lui indiquer la taille de l'objet à supprimer.


    C'est quoi d'ailleurs la différence entre le heap, et ce qu'on appelle "free store"?

Discussions similaires

  1. Différence entre TRUNCATE et DELETE ?
    Par HRS dans le forum SQL
    Réponses: 18
    Dernier message: 12/08/2011, 16h07
  2. différence entre delete et delete[]
    Par deubelte dans le forum C++
    Réponses: 7
    Dernier message: 25/02/2009, 03h30
  3. [BDE][TTABLE] différence entre EMPTY et DELETE
    Par cal dans le forum Bases de données
    Réponses: 1
    Dernier message: 15/02/2008, 08h04
  4. Différences entre delete table et delete from table
    Par pegase06 dans le forum Administration
    Réponses: 3
    Dernier message: 16/02/2007, 15h25
  5. Réponses: 3
    Dernier message: 07/05/2002, 16h06

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