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 :

operator new sans delete


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé Avatar de babar63
    Homme Profil pro
    Développeur jeux vidéos/3d Temps réel
    Inscrit en
    Septembre 2005
    Messages
    241
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Développeur jeux vidéos/3d Temps réel

    Informations forums :
    Inscription : Septembre 2005
    Messages : 241
    Par défaut operator new sans delete
    Bonjour à tous,
    Je suis actuellement dans la lecture d'un excellent bouquin sur la programmation de jeu, une partie traite des classes optionnelles voila un bout du 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
    // Base :
    template <unsigned long size>
    class optional_base
    {
    public:
    	optional_base();
    	optional_base(const optional_base &t);
     
    	optional_base & operator = (const optional_base &t);
     
    	bool const Valid() const;
    	bool const UnValid() const;
     
    protected:
    	bool m_bValid;
    	char m_data[size];
    };
     
    // Optional :
    template <class T>
    class optional : public optional_base<sizeof(T)>
    {
    public:
     
    	// Constructeurs...
    	// Operateurs...
    private:
     
    	const T * const GetT() const	{ return reinterpret_cast<const T * const>(m_data); }
    	T * const GetT()		{ return reinterpret_cast<T * const>(m_data); }
    	void Construct(const T &t)	{ new (GetT()) T(t); }
    	void Destroy()			{ GetT()->~T(); }
    };
    Seulement c'est la première fois que je vois l'opérateur new utilisé de cette manière, il n'y a de delete associé nulle part dans le code et GetT dans ce cas retourne un T*const donc les données ne sont pas sencé être modifié sauf si j'ai rien compris....... Si vous pouviez m'éclairer sur ce mystère , si il faut plus de détail sur le code n'hésitez pas à demander
    Merci d'avance

  2. #2
    Membre Expert

    Profil pro
    Inscrit en
    Juin 2006
    Messages
    1 294
    Détails du profil
    Informations personnelles :
    Localisation : Royaume-Uni

    Informations forums :
    Inscription : Juin 2006
    Messages : 1 294
    Par défaut
    Salut,

    C'est un placement new, cf. cette entrée de la FAQ.
    Un new "normal" est séparé en deux : allocation de la mémoire et initialisation, un placement new (comme son nom l'indique un peu) se contente d'effectuer la partie initialisation (donc d'appeler le constructeur en gros).

    edit : il y a une ) en trop dans le corps de Construct a priori.

    MAT.

  3. #3
    Membre émérite Avatar de MatRem
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    750
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 750
    Par défaut
    Si la méthode retourne un T * const, alors c'est le pointeur qui est constant, pas la donnée pointée .

    C'est d'ailleurs parceque la donnée retournée peut être modifiée que la fonction elle même n'est pas const.

  4. #4
    Membre confirmé Avatar de babar63
    Homme Profil pro
    Développeur jeux vidéos/3d Temps réel
    Inscrit en
    Septembre 2005
    Messages
    241
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Développeur jeux vidéos/3d Temps réel

    Informations forums :
    Inscription : Septembre 2005
    Messages : 241
    Par défaut
    il y a une ) en trop dans le corps de Construct a priori
    Petite faute d'inattention c'est réglé... Merci beaucoup pour le lien sur la faq je l'avais loopé . En tout cas tout est limpide désormais concernant la syntaxe
    Si la méthode retourne un T * const, alors c'est le pointeur qui est constant, pas la donnée pointée
    A vrai dire je ne me suis jamais vraiment posé la question pour moi "const T *" était associé à un pointeur constant et du coup "const T * const" à un pointeur constant sur donnée constante(d'après ma logique ) Mais alors ce que je comprend pas c'est pourquoi utiliser ces deux syntaxes pour définir la même chose mais surtout pourquoi mettre deux 'const' sachant que l'un d'entre eux ne veut strictement rien dire....
    En tout cas merci beaucoup pour votre aide

    Edit : Finalement le compilateur ne semble pas apprécier sans les parenthèse donc en fait il en manquait une je suppose, pour compiler :

  5. #5
    Expert confirmé

    Inscrit en
    Août 2006
    Messages
    3 967
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 3 967
    Par défaut
    Wue,
    Citation Envoyé par babar63 Voir le message
    alors ce que je comprend pas c'est pourquoi utiliser ces deux syntaxes pour définir la même chose mais surtout pourquoi mettre deux 'const' sachant que l'un d'entre eux ne veut strictement rien dire....
    Attention : un pointeur constant signifie qu'on ne peut pas le modifier, n'est pas la même chose que "données pointées constantes".

    Par exemple, avoir un pointeur constant n'interdit absolument pas de modifier les données pointées, SAUF si elles-mêmes sont déclarées constantes.

  6. #6
    Membre émérite Avatar de MatRem
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    750
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 750
    Par défaut
    Pour être tout à fait précis sur la constance avec les pointeurs :

    La donnée et le pointeur sont constants :
    const T * const ou T const * const

    ex :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    int i, j;
    int const * const p_i = &i;
     
    //on ne peut pas modifier i à partir de  p_i
    //*p_i = 10 interdit
     
    //on ne peut pas modifier p_i
    //p_i = &j interdit

    La donnée est constante mais pas le pointeur :
    const T * ou T const *
    ex :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    int i, j;
    int const * p_i = &i;
     
    //on ne peut pas modifier i à partir de  p_i
    //*p_i = 10 interdit
     
    //on peut modifier p_i
    p_i = &j; //ok

    Le pointeur est constant mais pas la donnée :
    T * const
    ex :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    int i, j;
    int * const p_i = &i;
     
    //on peut modifier i à partir de  p_i
    *p_i = 10; //ok
     
    //on ne peut pas modifier p_i
    //p_i = &j interdit

    Pour faciliter la mémorisation de ce qui est constant, le mieux est de tojours utiliser la syntaxe const après (T const * const), puisque pour les pointeurs constants c'est obligé.
    Dans ce cas ce qui est constant se situe avant le const.
    Et puis cette règle n'induit pas vraiment en erreur dans le cas ou on utilise le const avant (const T * const) puisqu'on voit vite qu'il n'y a rien avant.


    La en parle

  7. #7
    Membre chevronné
    Profil pro
    Inscrit en
    Février 2008
    Messages
    439
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 439
    Par défaut
    Citation Envoyé par MatRem Voir le message
    Si la méthode retourne un T * const, alors c'est le pointeur qui est constant, pas la donnée pointée .
    On ne peut pas renvoyer un scalaire constant en C++. Dans :
    le const est tout simplement ignoré, comme dans :

  8. #8
    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 corrector Voir le message
    le const est tout simplement ignoré, comme dans :
    Ce n'est pas tout à fait vrai. Vue de l'extérieur, cette fonction est effectivement identique à si on avait déclaré Mais vue de l'intérieur, i est une variable constante, ce qui ne serait pas le cas sinon (ce serait juste une variable dont les modifications ne seraient pas visible du code appelant).
    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.

  9. #9
    Inactif  
    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    1 958
    Détails du profil
    Informations personnelles :
    Âge : 60
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 1 958
    Par défaut
    Citation Envoyé par corrector Voir le message
    le const est tout simplement ignoré, comme dans :
    Comme le dit JolyLoic, c'est faux ce que tu dis. Si tu essaies de compiler ceci
    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int identite (const int i)
    {
       i = 1 ;
       return i ;
    }
    Tu obtiens une erreur à la compilation. En fait, il serait intelligent d'en mettre régulièrement. Cela rajoute une sécurité supplémentaire.

  10. #10
    Membre chevronné
    Profil pro
    Inscrit en
    Février 2008
    Messages
    439
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 439
    Par défaut
    Citation Envoyé par Garulfo Voir le message
    Comme le dit JolyLoic, c'est faux ce que tu dis. Si tu essaies de compiler ceci
    Code cpp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int identite (const int i)
    {
       i = 1 ;
       return i ;
    }
    Tu obtiens une erreur à la compilation.
    Il ne faut pas plus lire dans ce que j'ai écris que ce que j'ai écris :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int identite (const int i);
    est synonyme de
    Dans une définition de fonction, ça n'est pas équivalent évidemment.

    Citation Envoyé par Garulfo Voir le message
    En fait, il serait intelligent d'en mettre régulièrement. Cela rajoute une sécurité supplémentaire.
    Je ne suis pas sûr : est-ce que ce genre d'erreurs se arrive vraiment?

  11. #11
    Membre chevronné
    Profil pro
    Inscrit en
    Février 2008
    Messages
    439
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 439
    Par défaut
    Citation Envoyé par babar63 Voir le message
    Je suis actuellement dans la lecture d'un excellent bouquin
    Bof...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    template <unsigned long size>
    class optional_base
    {
    	char m_data[size];
    };
     
    template <class T>
    class optional : public optional_base<sizeof(T)>
    {
    	void Construct(const T &t)	{ new (GetT()) T(t); }
    };
    Qu'est-ce qui va garantir l'alignement de m_base? Comment ce code peut avoir la moindre chance de marcher?

  12. #12
    Membre confirmé Avatar de babar63
    Homme Profil pro
    Développeur jeux vidéos/3d Temps réel
    Inscrit en
    Septembre 2005
    Messages
    241
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Développeur jeux vidéos/3d Temps réel

    Informations forums :
    Inscription : Septembre 2005
    Messages : 241
    Par défaut
    Il s'agit de Game Coding Complete (Second Edition). Et oui je confirme le livre est excellent , même si il est possible de trouver quelques erreur de code sur presque 900 pages je pense que ce code a du marcher d'une manière ou d'une autre, il est présenté comme un des outils dont utilisé l'auteur (enfin la je m'avance un peu )... Pour en revenir à l'alignement peut être quelque chose ma échappé mais n'est-il pas possible de le désactiver simplement?

    EDIT : En fait c'est stupide le sizeof en revanche garantit bien l'alignement...

  13. #13
    Membre chevronné
    Profil pro
    Inscrit en
    Février 2008
    Messages
    439
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 439
    Par défaut
    Citation Envoyé par babar63 Voir le message
    Il s'agit de Game Coding Complete (Second Edition). Et oui je confirme le livre est excellent , même si il est possible de trouver quelques erreur de code sur presque 900 pages je pense que ce code a du marcher d'une manière ou d'une autre
    Sur certains processeur les accès non alignés sont "seulement" beaucoup plus lents. (Pour des jeux c'est fâcheu.)

    Citation Envoyé par babar63 Voir le message
    (enfin la je m'avance un peu )... Pour en revenir à l'alignement peut être quelque chose ma échappé mais n'est-il pas possible de le désactiver simplement?
    C'est une caractéristique du processeur.

    Citation Envoyé par babar63 Voir le message
    EDIT : En fait c'est stupide le sizeof en revanche garantit bien l'alignement...
    Pardon?

  14. #14
    Membre confirmé Avatar de babar63
    Homme Profil pro
    Développeur jeux vidéos/3d Temps réel
    Inscrit en
    Septembre 2005
    Messages
    241
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France

    Informations professionnelles :
    Activité : Développeur jeux vidéos/3d Temps réel

    Informations forums :
    Inscription : Septembre 2005
    Messages : 241
    Par défaut
    Voila ce que je pense : Les données de l'objet T est représenté par un tableau de char, par défaut cette structure est alignée, et la taille du tableau devrait être correct puisqu'on utilise sizeof(T). Quand je disais qu'il garantissait bien l'alignement je voulais dire que le reinterpret_cast fonctionnerait (du moins je pense...). Pour ce qui est du placement new c'était le sujet du topic donc forcément je ne vais pas trop m'avancer mais j'ai cru comprendre que c'était simplement l'appel au constructeur de l'objet (l'allocation étant déjà effectué), le pointeur sur la zone étant valide et la taille correct je ne vois pas d'où vient le problème... Peut-tu me dire sur quel point je me trompe?

    EDIT : En relisant plus correctement la faq c'est vrai qu'il est bien préciser que l'objet doit être correctement aligné pour utiliser le placement new, donc si c'est le cas aucun problème pour le code je suppose? Par défaut le compilateur aligne bien non? il y aurait donc danger seulement si on "trafique" l'alignement? ...Dites moi si j'ai tout faux

    EDIT2 : En tout cas je crois que je vais devoir réviser mes cours, réguler mon optimisme sur le livre et faire des tests histoire de mieux comprendre

  15. #15
    Membre chevronné
    Profil pro
    Inscrit en
    Février 2008
    Messages
    439
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2008
    Messages : 439
    Par défaut
    Citation Envoyé par babar63 Voir le message
    Voila ce que je pense : Les données de l'objet T est représenté par un tableau de char, par défaut cette structure est alignée,
    Pourquoi le serait-elle?

    Citation Envoyé par babar63 Voir le message
    et la taille du tableau devrait être correct puisqu'on utilise sizeof(T).
    Ce n'est pas le problème. C'est l'alignement qui est en cause.

    Citation Envoyé par babar63 Voir le message
    Quand je disais qu'il garantissait bien l'alignement je voulais dire que le reinterpret_cast fonctionnerait (du moins je pense...).
    Au delà du reinterpret_cast (qui sur les archi courantes "fonctionne" toujours), il faut pouvoir construire et manipuler un objet à cette adresse, sans générer un segfault ou équivalent.

    Citation Envoyé par babar63 Voir le message
    Pour ce qui est du placement new c'était le sujet du topic donc forcément je ne vais pas trop m'avancer mais j'ai cru comprendre que c'était simplement l'appel au constructeur de l'objet (l'allocation étant déjà effectué),
    C'est exactement ça.

    Citation Envoyé par babar63 Voir le message
    le pointeur sur la zone étant valide et la taille correct je ne vois pas d'où vient le problème...
    Le problème vient de ce que le pointeur n'est pas valide, car non-aligné.

    Citation Envoyé par babar63 Voir le message
    Peut-tu me dire sur quel point je me trompe?
    Sur le fait que l'alignement est un "non-problème". (Méfiez-vous des "non-problèmes".)

    Citation Envoyé par babar63 Voir le message
    Par défaut le compilateur aligne bien non? il y aurait donc danger seulement si on "trafique" l'alignement? ...Dites moi si j'ai tout faux
    Selon la norme, tu as tout faux.

    Après, je ne sais pas ce que fait "par défaut" ton compilateur.

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

Discussions similaires

  1. Redéfinition opérateurs new et delete globaux
    Par bolhrak dans le forum C++
    Réponses: 8
    Dernier message: 30/07/2007, 11h34
  2. surdefinition operateur new et delete
    Par johjoh dans le forum C++
    Réponses: 23
    Dernier message: 08/12/2006, 10h10
  3. intrigue sur la surcharge du new et delete
    Par swirtel dans le forum C++
    Réponses: 12
    Dernier message: 07/09/2006, 15h23
  4. Segmentation fault sur new[] et delete[]
    Par Don ViP dans le forum C++
    Réponses: 4
    Dernier message: 30/04/2006, 00h29
  5. Namespace et surcharge operator new/delete
    Par ZeLegolas dans le forum C++
    Réponses: 11
    Dernier message: 26/07/2005, 13h55

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