[C++ débutant] Différence entre un New et un "Type nom" ?

Différence entre un New et un "Type nom" ? [C++ débutant] - C++ - Programmation

Marsh Posté le 21-02-2006 à 00:39:31    

Petite question rapide:
 
Y-a-t'il une différence entre:
 

Code :
  1. Triangle *monTriangle = new Triangle("NomDuTriangle", "Triangle", 7, coord1, coord2, coord3);


 

Code :
  1. Triangle monTriangle("NomDuTriangle", "Triangle", 7, coord1, coord2, coord3);


 
?  
 
Tous 2 marchent, et le deuxième est plus "clair" je trouve... mais peut-être qu'il y a un interêt à utiliser le new ?


---------------
Pier noir la mèr - La chanson par HFR Band - Topic TrueCrypt
Reply

Marsh Posté le 21-02-2006 à 00:39:31   

Reply

Marsh Posté le 21-02-2006 à 08:22:42    

Bien sur qu'il y en a un : essaie donc, sans le new, d'implementer une classe de liste chainee ou de tableau redimensionnable, tu verras bien la ou ca coince!
 
L'interet du new, pour faire simple, c'est que c'est toi qui decide de la duree de vie de ton objet, alors que si tu le declares en tant que variable locale il meurt a la fin du bloc. Par consequent tout ce qui a ete alloue avec new a besoin d'etre explicitement desalloue via delete.
 


Message édité par Ace17 le 21-02-2006 à 08:24:05
Reply

Marsh Posté le 21-02-2006 à 10:02:46    

oui, sur le principe c'est exactement la meme chose.  
 
sauf qu'avec le new, il ne faut pas oublier de faire le  "delete monTriangle" quand tu n'en as plus besoin.
 
En tant que "debutant", tu n'as peut etre pas bien compris la nuance de l'allocation dynamique...
Les objet "vivent" tant que tu n'as pas fais de delete, il sont donc disponible partout dans l'application du moment que tu as stocké leur pointeur quelque part; contrairement aux objets alloués statiquement (sans new) qui meurent à la fin du bloc où ils sont déclarés ( comme le dit Ace17 )
 
Un autre inconveignant a utiliser les pointeurs quand on en pas besoin, c'est l'utilisation du ->  et de *  pour acceder à l'objet lui meme.C'est quand meme moins lisible qu'un simple . (point)

Reply

Marsh Posté le 21-02-2006 à 11:34:29    

Hm merci  :jap:  
 
Dans l'exo que j'ai à rendre, j'utilise effectivement une liste châinée. Dans le main(), j'ai donc besoin d'une seule liste principale qui va contenir mes objets (triangles et autres formes, ainsi que des listes de formes). J'ai donc déclaré ma liste Principale sans New, la "fin du bloc" étant la fin du main ... non ?
 
Enfin je comprends la différence entre les 2 grace à vos explications, mais je ne suis pas sûr d'avoir compris quelle méthode utiliser dans mon cas ^^
 
Pour vous montrer de quoi je parle, voici le shéma que j'ai fait pour ma structure de données:
http://orgasm.free.fr/hfr/shemac++.jpg
 
et voici le sujet initial:
http://orgasm.free.fr/hfr/sujetc++.jpg
 
Pour toutes les formes que je vais créer, il faudra donc les créer en new, et ma liste je peux la laisser en "statique" dans le main ? (pareil pour les groupes ?)
 
 :jap:


---------------
Pier noir la mèr - La chanson par HFR Band - Topic TrueCrypt
Reply

Marsh Posté le 21-02-2006 à 13:14:44    

Si tout est géré dans le main, je ne vois pas ce qui t'empêche de créer les objets sur la pile (sans le new qui utilise le tas) et de faire ton association dans la liste chaînée en passant un pointeur pour chacun.


Message édité par slash33 le 21-02-2006 à 13:17:14
Reply

Marsh Posté le 21-02-2006 à 14:28:21    


Le new permet un passage de paramètres par pointeur, le deuxième example permet le passage par valeur.
 
Si tu utilise tout le temps new, tu devra gérer l espace mémoire en supprimant toi même les variables avec delete. Ta variable est un pointeur vers l emplacement mémoire qui contient les valeures. Il est possible de récupérer la valeure avec l opérateur *: par ex. (*triangle);
 
Avec le passage par valeur une copie de l objet est necessaire. L objet est automatiquement détruit quand le bloc est refermé (à l aide de }). Essayer d accéder à une variable en dehors de son bloc produit une erreure de compilation. Il est possible de connaitre l emplacement mémoire avec l opérateur &: par ex. (&triangle).
 
Concrètement, avec new et delete tu as besoin uniquement de définir un constructeur et un destructeur. Tu doit ensuite gérer la vie de tes variables, sinon tu risque une erreure à l exécution (comme accéder à un pointeur avant un new ou après un delete). Le sys. dexploitation fermera de force ton programme dans ce cas.
 
Avec le passage par valeur tu doit en plus définir le constructeur de copie:
ClassName(const ClassName& );
et l opérateur de copie:
ClassName& operator=(const ClassName& );
(note: sauf dans le cas particulier ou tu n a pas besoin de constructeur/destructeur, les opérateurs qui te sont alors fournis par défaut conviennent).
Enfin, tu doit tout de même te décider sur la manière de gérer les propriétés de ton objet: si ton objet necessite beaucoup de mémoire (une image par example), il n est pas très judicieux de laisser l opérateur de copie doubler de grande quantités de mémoire. Tu peut utiliser des passages par paramètres de cette façon:
void Fonction(ClassName& );
qui passe en réalité un pointeur sur ton objet (celui ci ne doit par conséquent pas être temporaire), en évitant la copie.
 
Il y a beaucoup de façon de gérer la mémoire, et je n ai donné l example que des façons naturellement supportées par C++. Tu peut toi même élaborer des gestions de mémoire plus complexes, mais gérées lors de l exécution.
 
Pour une liste chaînée, tu as le choix entre une liste autodelete (qui se charge de créer/supprimer les objets lorsque la liste est vidée ou les éléments insérés/supprimés), et une liste sans autodelete qui stocke uniquement des pointeurs et laisse le programmeur en charge de créer/supprimer les objets en dehors de la liste.
 
L autodelete est une solution complète de liste, aussi appelé liste de valeur. Sans autodelete la liste est plus facile à écrire, elle est aussi appelée liste de pointeurs.
 
Pour une liste tu peut aussi définir les opérateurs:
const Objet& operator [] (unsigned int); // par ex. Triangle t=liste[i]
ObjetElement& operator [] (unsigned int); // par ex. liste[i]=Triangle(...);
Et les opérateurs d ajout:
Liste& operator << (const Objet& ); // ajout objet
Liste& operator << (const List& ); // ajout liste
 
Bon courage!

Reply

Marsh Posté le 21-02-2006 à 15:40:13    

OK, en fait ta liste principale est une Forme  (classe de base qui contiendra des formes).
Oui, Cette liste peut etre declarée dans le main en statique.
 
Cette liste  ( de type Forme) aura des methodes pour ajouter des formes ( Triangle, Rectangle ) et contiendra un pointeur vers une liste chainée d'objet de type Forme.
C'est donc un pointeur car la liste chainée est dynamique ( 0 ou n objets dans la liste ), le nombre de poste n'est pas définit à l'avance.
Les objets de la liste sont donc bien créés par des news.
 
Pense bien a faire des methodes de suppression des objet en memoire  
 
C'est un peu chaud comme projet, rien que le parser de ligne de command !  d'ailleurs il y avait déjà une question a ce sujet sur ce forum !  toi peut etre !?


Message édité par ChristianS_ le 21-02-2006 à 15:51:03
Reply

Marsh Posté le 21-02-2006 à 16:36:23    

Merci beacoup pour toutes ces précisions ... :)
 
Pour ma liste, je n'ai pas fait une liste de pointeurs, mais d'objets !
 
Mon .h:
 

Code :
  1. #ifndef _Liste_h
  2. #define _Liste_h
  3. #include <iostream.h>
  4. #include "objet.h"
  5. //Liste d'objets doublement chaînée
  6. class Liste
  7. {
  8. friend class Iterateur;
  9. friend class Iterateur_w;
  10. private:
  11.  //Noeud de la liste
  12.  class Node
  13.  {
  14.   friend class Objet;
  15.   friend class Iterateur;
  16.   friend class Iterateur_w;
  17.   friend class Liste;
  18.   public:
  19.    Node();
  20.    Node(Objet maValeur);
  21.    Node(Objet maValeur, Node *suivant, Node *precedent);
  22.    ~Node();
  23.    
  24.   private:
  25.    Objet valeur;
  26.    Node *suivant;
  27.    Node *precedent;
  28.    bool estLibre;
  29.  };
  30.  Node *tete;
  31.  Node *queue;
  32.  int nbElements;
  33. public:
  34.  Liste();
  35.  ~Liste();
  36.  void print() const;
  37.  int getNbElements() const;
  38.  void incNbElements();
  39.  void decNbElements();
  40.  bool estVide() const;
  41.  void ajoutFin(Objet);
  42.  void ajoutTete(Objet);
  43.  void supprimerTete();
  44.  void supprimerQueue();
  45.  Objet valeurTete() const;
  46.  Objet valeurQueue() const;
  47. };
  48. #endif


 
Et j'ajoute donc directement les objets par recopie. Mais maintenant, que je fasse un triangle avec un "new" ou sans, je peux l'ajouter dans les 2 cas avec les méhodes de ma liste !
 
Sinon pour parcourir la liste, j'ai un itérateur:
 

Code :
  1. #ifndef _Iterateur_h
  2. #define _Iterateur_h
  3. #include <iostream.h>
  4. #include "liste.h"
  5. //Itérateur de lecture qui ne fait que consulter une liste
  6. class Iterateur
  7. {
  8. protected:
  9.  Liste::Node **actuel;
  10.  Liste *liste;
  11. public:
  12.  Iterateur(const Liste & );
  13.  virtual ~Iterateur();
  14.  void avance();
  15.  void recule();
  16.  void retourTete();
  17.  Objet  valeur() const;
  18.  bool finDeListe() const;
  19. };
  20. #endif


 
et un iterateur d'écriture, hérité de l'itérateur 'normal":
 

Code :
  1. #ifndef __Iterateur_w_h
  2. #define __Iterateur_w_h
  3. #include "liste.h"
  4. #include "iterateur.h"
  5. // Itérateur d'écriture qui modifie une Liste
  6. class Iterateur_w : public Iterateur
  7. {
  8. public:
  9. Iterateur_w(Liste & );
  10. ~Iterateur_w();
  11. void ajouter(Objet, Liste& );
  12. void supprimer(Liste& );
  13. };
  14. #endif;


 
Grace à tout ça, je peux manipuler ma liste comme je veux, y ajouter des Formes (qui ne sont rien d'autres que des "objets" particuliers !)
 
Comme décrit ds le shéma ( http://orgasm.free.fr/hfr/shemac++.jpg ) en haut à droite, "tout est objet" ... de façon à pouvoir ajouter ET des formes ET des groupes de formes dans ma liste principale.
 
Maintenant, vu que tout va se jouer dans le main() avec une seule liste principale (qui contiendra mes formes, ou mes groupes de formes (qui sont des nouvelles listes de formes ^^)), je peux donc tout créer sans new ... ? L'analyseur de ligne de commande ne va que disséquer la commande entrée, et renvoyer au main un constructeur d'une forme, comme par ex mon triangle  
 

Code :
  1. Triangle monTriangle("NomDuTriangle", "Triangle", 7, coord1, coord2, coord3);


 
J'ai bon ? :D
 
Le sujet est effectivement plutot dur, surtout pour nous qui n'avons jamais fait ni de C (très peu) ni de C++ ... mais que du Java ^^ Et en Java, les constructeurs par recopie et tout ça, ça n'existe pas. Tout comme les pointeurs, d'ailleurs. Du coup, désolé d'insister un petit peu la dessus ... m'enfin vous m'avez déja bien aidé. L'autre question posée sur le forum a du etre postée par mon binome de Projet ^^
 
 :hello:


---------------
Pier noir la mèr - La chanson par HFR Band - Topic TrueCrypt
Reply

Marsh Posté le 21-02-2006 à 19:09:10    

Ça me semble nickel.
 
Tu devrait quand même utiliser:
void ajoutFin(Objet& );
void ajoutTete(Objet& );
Node::Node(Objet& );
etc...
Ça permet au compilateur de lui indiquer de passer le pointeur seulement au lieu d une copie de l objet.
 
Perso, j aurais appelé la classe Liste un Arbre, simple nuance de vocabulaire.

Reply

Marsh Posté le 21-02-2006 à 20:38:34    

iostream.h n'est pas standard (et il est inutile dans le .h, peut etre dans le .cpp ...), il faut utiliser iostream

Reply

Marsh Posté le 21-02-2006 à 20:38:34   

Reply

Marsh Posté le 21-02-2006 à 21:25:52    

nargy a écrit :

Ça me semble nickel.
 
Tu devrait quand même utiliser:
void ajoutFin(Objet& );
void ajoutTete(Objet& );
Node::Node(Objet& );
etc...
Ça permet au compilateur de lui indiquer de passer le pointeur seulement au lieu d une copie de l objet.
 
Perso, j aurais appelé la classe Liste un Arbre, simple nuance de vocabulaire.


 
Mais si je fais ça, je serais obligé de créer tous mes objets à insérer en New, non ? Si c'est ça, j'ai compris l'intérêt :D Sinon, non  [:ddr555]  
 
Pour iostream, par contre, je n'ai pas compris. Je sais que je peux laisser de coté le "h", mais je pensais que ça revenait au même ?


---------------
Pier noir la mèr - La chanson par HFR Band - Topic TrueCrypt
Reply

Marsh Posté le 21-02-2006 à 21:45:28    

ParadoX a écrit :

Mais si je fais ça, je serais obligé de créer tous mes objets à insérer en New, non ? Si c'est ça, j'ai compris l'intérêt :D Sinon, non  [:ddr555]


 
il y a deux facon de passer une variable à une fonction/méthode en C++, passage par valeur (par défaut) ou passage par référence (avec le & apres le type de l'argument dans le prototype de la fonction). Ces deux méthodes sont complement indépendantes du type d'allocation de la variable (c'est simple, ca n'a rien à voir)
 
quand tu passes un objet par valeur, tu récupère une copie dans la fonction, si tu le modifies ca ne le modifieras pas dans le code appelant (c'est en fait une variable local à la fonction), sémantiquement ca convient dans tout les cas ou on n'a pas besoin de conserver les modifications faites sur l'objet apres l'appel de la fonction
 
quand tu passe un objet par référence, tu récuperes dans la fonction une référence (!= de pointeur) sur l'objet dans le code apelant, cette référence est comme un alias de l'objet, c'est juste un nom qui désigne le meme objet. de ce fait toute les modifications faites sur l'objet dans la fonctions porteront apres l'appel de la fonction car c'est le meme objet que tu manipulais. sémantiquement ca sert principalement à pouvoir modifier un parametre de la fonction, mais ca peut aussi etre utilisé (pour des raisons d'efficacité) pour éviter la copie inutile d'un objet (qui peut etre tres lourde alors qu'un référence peut etre assimilée à un pointeur mais ca on s'en fou) sans toutefois avoir besoin de le modifier, dans ce cas on ajoute le mot cle 'const' avant (ou apres) le type qui indique le parametre ne pourra pas etre modifier dans la fonction bien qu'il s'agisse d'un passage par référence
 
du coup c'est déja plus logique d'écrire
 
void ajoutFin(const Objet& );
void ajoutTete(const Objet& );

Message cité 2 fois
Message édité par skelter le 21-02-2006 à 21:46:51
Reply

Marsh Posté le 21-02-2006 à 21:51:27    

Non, que dalle, examples:
 
int length(Image* i) { return i->mylength; }
- passe un pointeur (adresse mémoire de l objet = copier un nombre entier d environ 4 octets). retourne une copie du champs longueure.
 
int length(Image i) { return i.mylength; }
- recopie une image de 15MégaOctets en mémoire, plus les autres champs, puis appelle la fonction qui détruit la copie de 15MégaOctets devenue inutile avant de retourner une copie du champs longueure.
 
int length(Objet& o) { return o.mylength; }
- passe un pointeur (environ 4 octets). retourne une copie du champs longueure.
 
Il est fortement conseillé de virer le .h pour raisons de portabilité obscures.
 

Reply

Marsh Posté le 21-02-2006 à 21:52:32    

ParadoX a écrit :


Pour iostream, par contre, je n'ai pas compris. Je sais que je peux laisser de coté le "h", mais je pensais que ça revenait au même ?


 
non, iostream.h et iostream sont bien deux headers différent, la différence c'est que iostream.h date du c++ pré standard et en gros quand le standard est arrivé il a été décidé que tout les headers publiques de la bibliothèque standard ne devaient etre sans extension (et tout les noms dans le namespace std). cependant les compilateurs  fournissent encore les versions avec .h (et nom dans le namespace globale) pour la rétro compatibilité.
 
si ton prof te dis d'utiliser iostream.h c'est qu'il ne connais pas le c++

Reply

Marsh Posté le 21-02-2006 à 21:55:42    

C ça, passage par référence, je me rappelais plus le nom... en réalité ça utilise un pointeur (caché). Dans certains cas très rares le compilateur peut gnogner contre l utilisation de référence d un objet temporaire. Dans ce cas forcer une copie de l objet à l aide de la déclaration d une variable supplémentaire. Cela indique que l opération souhaitée n est possible qu a la condition de copier l objet préalablement.

Reply

Marsh Posté le 21-02-2006 à 21:58:37    

Citation :

int length(Image* i) { return i->mylength; }
- passe un pointeur (adresse mémoire de l objet = copier un nombre entier d environ 4 octets). retourne une copie du champs longueure.


 
oui, pour ne pas embrouiller autant dire recopie d'une variable de type pointeur sur image, parce que ca reste du passage par valeur, et surtout c'est 'c-style' on preferera un passage par référence constante dans ce cas en c++
 

Citation :

int length(Objet& o) { return o.mylength; }
- passe un pointeur (environ 4 octets). retourne une copie du champs longueure.


 
ca passe une référence, on s'en fou qu'au niveau du code généré c'est comme si on passait un pointeur, les référence c'est justement pour ne plus avoir à se faire chier avec ca alors pas besoin de remettre ca sur le tapis

Reply

Marsh Posté le 21-02-2006 à 22:00:03    

skelter a écrit :

il y a deux facon de passer une variable à une fonction/méthode en C++, passage par valeur (par défaut) ou passage par référence (avec le & apres le type de l'argument dans le prototype de la fonction). Ces deux méthodes sont complement indépendantes du type d'allocation de la variable (c'est simple, ca n'a rien à voir)
 
quand tu passes un objet par valeur, tu récupère une copie dans la fonction, si tu le modifies ca ne le modifieras pas dans le code appelant (c'est en fait une variable local à la fonction), sémantiquement ca convient dans tout les cas ou on n'a pas besoin de conserver les modifications faites sur l'objet apres l'appel de la fonction
 
quand tu passe un objet par référence, tu récuperes dans la fonction une référence (!= de pointeur) sur l'objet dans le code apelant, cette référence est comme un alias de l'objet, c'est juste un nom qui désigne le meme objet. de ce fait toute les modifications faites sur l'objet dans la fonctions porteront apres l'appel de la fonction car c'est le meme objet que tu manipulais. sémantiquement ca sert principalement à pouvoir modifier un parametre de la fonction, mais ca peut aussi etre utilisé (pour des raisons d'efficacité) pour éviter la copie inutile d'un objet (qui peut etre tres lourde alors qu'un référence peut etre assimilée à un pointeur mais ca on s'en fou) sans toutefois avoir besoin de le modifier, dans ce cas on ajoute le mot cle 'const' avant (ou apres) le type qui indique le parametre ne pourra pas etre modifier dans la fonction bien qu'il s'agisse d'un passage par référence
 
du coup c'est déja plus logique d'écrire
 
void ajoutFin(const Objet& );
void ajoutTete(const Objet& );


 
ça je pense avoir compris, mais ma question portait plutot sur le type d'argument que je donne a ma méthode: Actuellement, je lui donne un Objet en valeur. Si je le passe en référence, je serais obligé de modifier la façon dont je crée les objets que je vais lui passer ?  
 
Exemple concret: L'implémenation de la méthode "ajouter en tête" (telle qu'elle est actuellement)
 

Code :
  1. //Ajout en tête de Liste
  2. void Liste::ajoutTete(Objet maValeur)
  3. {
  4. //Creation et remplissage du nouveau noeud
  5. Node *nouv = new Node(maValeur, tete, NULL);
  6. //2 cas: La liste est vide, ou elle ne l'est pas
  7. if(!estVide())
  8. {
  9.  tete = nouv;
  10. }
  11. else
  12. {
  13.  tete = nouv;
  14.  queue = nouv;
  15. }
  16. this->nbElements ++;
  17. }


 
Et pour l'utiliser, je fais comme cela:
 

Code :
  1. Liste maListe;
  2. Iterateur_w monIterateur(maListe);  //Commentaire HFR: Un itérateur prends une liste en référence ! (et j'en vois l'utilité !)
  3. Triangle monTriangle("TimLeTriangle", "Triangle", 7, coord1, coord2, coord3);
  4. maListe.ajoutTete(monTriangle);


 
Je pourrai quand-même l'utiliser comme ça, mon ajout, si je lui change la signature "objet" en "objet&" ? (je testerai demain, pas possible là ^^)
 
 :jap:  


---------------
Pier noir la mèr - La chanson par HFR Band - Topic TrueCrypt
Reply

Marsh Posté le 21-02-2006 à 22:04:43    

ParadoX a écrit :

Si je le passe en référence, je serais obligé de modifier la façon dont je crée les objets que je vais lui passer ?  


 

skelter a écrit :

il y a deux facon de passer une variable à une fonction/méthode en C++, passage par valeur (par défaut) ou passage par référence (avec le & apres le type de l'argument dans le prototype de la fonction). Ces deux méthodes sont complement indépendantes du type d'allocation de la variable (c'est simple, ca n'a rien à voir)


 
ben ouai, qu'est ce qu'on en a foutre de comment à été aloué l'objet ?


Message édité par skelter le 21-02-2006 à 22:06:13
Reply

Marsh Posté le 21-02-2006 à 22:07:23    

Merci beacoup de ton aide  :jap:


---------------
Pier noir la mèr - La chanson par HFR Band - Topic TrueCrypt
Reply

Marsh Posté le 21-02-2006 à 22:13:57    

hehe. ok, pointeur, référence, c est la même chose. je ne souhaitait pas commencer une <<flame war>>.
Mais puisque le sujet est lancé: les références ne servent qu aux programmeurs trop fainéants pour taper ->.
hehe. je blague.
 
Sérieusement, le passage par référence laisse le compilateur trouver lui même un pointeur sur l objet, sans avoir à lui préciser explicitement ce pointeur à l aide de new. Mais il est toujours utile de connaître le fonctionnement de la compilation.  
Tu peux remplacer tous les Objet en Objet&. Si le compilateur ne trouve pas le pointeur lui même il te le dira.

Reply

Marsh Posté le 21-02-2006 à 22:19:12    

nargy a écrit :

hehe. ok, pointeur, référence, c est la même chose. je ne souhaitait pas commencer une <<flame war>>.


 
Sauf honteuse malversation, une reference "pointe" tjs vers quelque en vie. Tout leur interet est la
 
 

Citation :

Sérieusement, le passage par référence laisse le compilateur trouver lui même un pointeur sur l objet, sans avoir à lui préciser explicitement ce pointeur à l aide de new.


 
hen ?
 
 

nargy a écrit :


Tu peux remplacer tous les Objet en Objet&


 
ouais mais nan, ca se fait pas a la legere, ca se reflechi, ca se const-ise, ca se jauge, ca se tate
 

Citation :

Si le compilateur ne trouve pas le pointeur lui même il te le dira.


 
(re-hein)


Message édité par chrisbk le 21-02-2006 à 22:19:43
Reply

Marsh Posté le 21-02-2006 à 22:41:16    

heu, ok... ça devient technique.
Oui une référence pointe toujours sur quelquechose en vie. C est un des intérêts face aux pointeurs.
 
<<ca se fait pas a la legere>>
 
Entièrement d accord. En fait ça se prévoit. Dans le cas du code de Liste ça ne semble pas trop présenter de complications, étant donné la longueure du programme.
 
<<Si le compilateur ne trouve pas le pointeur lui même il te le dira. >>
 
Ça peut paraître obscur, certes. Disons qu un objet est stocké à un emplacement mémoire. Un pointeur ou une référence est un nombre qui est la <<coordonnée en mémoire>> de l objet. Ça prends beaucoup moins de place que l objet en entier.
 
Le seul cas pour lequel je suis sûr qu un objet n a pas d emplacement mémoire est lorsque l objet tient entièrement dans un registre. Dans ce cas, pas de référence possible vers l objet. D où warning du compilateur, qui est obligé de forcer à stocker l objet en mémoire centrale. Rem: dans ce cas une référence n est pas nécessaire car l objet est trop petit.
 
Ça m est arrivé plusieurs fois pourtant d avoir une erreure Fatale du compilateur dans une ligne telle que: a=b=(a+b)*c<<d , avec abcd des objets. Je n ai pas d example concret, mais utilisant GCC, j ai eu des erreures style: Cannot take address of temporary object. Si vous avez des explications à ça je veux bien (où est passé l objet?). Dans ce cas je déclare des variables pour stocker les résultats temporaires et ça compile. Peut être que j avais oublié un constructeur?
 

Reply

Marsh Posté le 21-02-2006 à 22:45:46    

Petite recherche sur internet et je trouve:
In C++, temporary objects are treated as const, so one way to solve the problem is to change
void test(MyClass & rTest)
to
void test(const MyClass &rTest)
 
Voilà, j ai l explication. En C++ les objets temporaires sont traité comme constants.

Reply

Marsh Posté le 21-02-2006 à 22:52:44    

Citation :


Le seul cas pour lequel je suis sûr qu un objet n a pas d emplacement mémoire est lorsque l objet tient entièrement dans un registre. Dans ce cas, pas de référence possible vers l objet. D où warning du compilateur, qui est obligé de forcer à stocker l objet en mémoire centrale.


 
Heuh je veux pas etre mechant, mais d'un point de vue programmeur, que l'objet tienne ou non dans un registre, on s'en fout. Tu peux avoir une reference vers un char si ca te chante, le compilo n'a rien a dire la dessus
 

Citation :

Rem: dans ce cas une référence n est pas nécessaire car l objet est trop petit.


 
heuh bah, heuh, t'es sur d'avoir compris l'interet d'une reference ?
 
 

Reply

Marsh Posté le 21-02-2006 à 22:53:54    

Autre explication:
<<Temporaries May Vanish Before You Expect>>
Les objets temporaire peuvent disparaîtres avant qu on s y attende.
Ça arrive en fait lorsque l on retourne une référence sur un membre d une classe. Dans le cas d un objet temporaire il peut être supprimé lorsque l on utilise la référence.
Certains compilateur n ont pas ce problème, mais c est pourtant le comportement requis pour un compilateur standardisé.
 

Reply

Marsh Posté le 21-02-2006 à 22:57:05    

Ouah! Je viens de relire.
Non une référence ne pointe pas toujours sur quelquechose en vie. C Dingue.

Reply

Marsh Posté le 22-02-2006 à 08:41:11    

Quelqu'un a t-il tenté de modéliser le problème de Paradox ?
 
As tu prévu le cas où un groupe tente de s'inclure lui même ?
Peut on définir des groupes croisés ?
 
a) (A - B) - C : 1 groupe G1 = (A,B)
b) (A - [B) - C] : 2 groupes croisés G1 = (A,B) et G2 = (B,C)
c) [(A - B) - C] : 2 groupes G1 = (A,B) contenu dans le groupe G2 = (G1,C)

Message cité 1 fois
Message édité par slash33 le 22-02-2006 à 08:43:47
Reply

Marsh Posté le 22-02-2006 à 08:53:17    

nargy a écrit :

Ouah! Je viens de relire.
Non une référence ne pointe pas toujours sur quelquechose en vie. C Dingue.


Code :
  1. Object* anObject = new Object();
  2. delete anObject; // détruit l'objet
  3. // le pointeur pointe sur une zone mémoire libérée!
  4. // Utilise la fonction de prototype FonctionUsingObject(const Object& )
  5. FonctionUsingObject(*anObject); // Erreur : référence sur un objet non valide!


Message édité par slash33 le 22-02-2006 à 08:55:56
Reply

Marsh Posté le 22-02-2006 à 08:55:27    

voila ce que j'entendais par "honteuse malversation" [:god]

Reply

Marsh Posté le 22-02-2006 à 08:57:11    

D'où l'intérêt des auto_ptr ?

Reply

Marsh Posté le 22-02-2006 à 10:04:33    

slash33 a écrit :

Quelqu'un a t-il tenté de modéliser le problème de Paradox ?
 
As tu prévu le cas où un groupe tente de s'inclure lui même ?
Peut on définir des groupes croisés ?
 
a) (A - B) - C : 1 groupe G1 = (A,B)
b) (A - [B) - C] : 2 groupes croisés G1 = (A,B) et G2 = (B,C)
c) [(A - B) - C] : 2 groupes G1 = (A,B) contenu dans le groupe G2 = (G1,C)


 
Hello !
 
Alors, pas de groupes croisés, si une figure est dans un groupe, elle n'est "plus libre" pour un autre groupe. En revanche, on doit pouvoir faire des groupes de groupes ... c'est pourquoi il est important qu'un groupe soit autant un "objet" qu'une simple figure !


---------------
Pier noir la mèr - La chanson par HFR Band - Topic TrueCrypt
Reply

Marsh Posté le 22-02-2006 à 10:05:15    

slash33 a écrit :

D'où l'intérêt des auto_ptr ?


 
whats teh rapport ? D'une maniere generale les conversions pointeur => reference, ca sent un peu du bout (et qu'on vienne pas me chier dans les bottes avec le return *this [:petrus75])


Message édité par chrisbk le 22-02-2006 à 10:05:47
Reply

Marsh Posté le 22-02-2006 à 16:17:29    

D'où l'intérêt du garbage collector ? :D

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed