Copie d'un std::vector [C/C++] - C++ - Programmation
Marsh Posté le 28-04-2008 à 15:02:18
- c'est l'operator= de ton MonObjet qui est pourri
- si c'est pas lui, c'est ton constructeur de copie
bref c'est dans MonObjet.
Marsh Posté le 28-04-2008 à 15:57:28
En fait, je n'ai pas un constructeur de copie dans mon objet ni une surcharge de l'opérateur.
C'est une solution que j'envisage.
Pour l'instant, je suis en train de créer une fonction copie.
Je vous tiens au courant ...
Marsh Posté le 28-04-2008 à 16:04:37
LaTex_man a écrit : En fait, je n'ai pas un constructeur de copie dans mon objet ni une surcharge de l'opérateur. |
la fonction de copie c'est ignoble. Si le constructeur par copie et operator= synthétisés ne sont pas bon,s c'est ça le problème, tu dois les définir explicitement et pas faire n'importe quoi avec une fonction de copie qui est inutile et inutilisable
Et si t'as des char*, remplace par string tout de suite.
Marsh Posté le 28-04-2008 à 18:28:23
Commandement n°1:
"La forme canonique de Coplien pour tes objets tu respecteras"
C'est comme les preservatifs, on doit jamais sortir sasn.
Toutes classe bien formée se doit d'exhiber :
- 1 constructeur par défaut
- 1 destructeur
- 1 constructeur de copie
- 1 opérateur d'affectation
sinon, GTFO
Marsh Posté le 29-04-2008 à 04:02:55
tout ce ceci a l'exception du constructeur par defaut est necessairement généré par le compilateur il me semble.
(le constructeur par defaut peut etre "désactivé" par la presence explicite d'un constructeur avec au moins un argument sans valeur par defaut)
il faudrait plutot préciser qu'il faut remplir la SEMANTIQUE de ces opérations histoire que ca fasse quelque chose qui respecte une charte de codage précise. (je connais pas le bonhomme coplien mais ptet que c'est ce qu'il dit lui aussi au fond)
genre : "un operateur de copie doit non seulement etre présent mais rendre l'objet destination indépendant de l'instance de sa source"
non ?
remarquez que les contenurs STL (string du moins) ne copient pas les données immediatement mais seulement sur modification d'une des opérandes. (late copy ou je sais plus le nom...)
bref il s'agit d'un systeme de reference count intelligent.
Marsh Posté le 29-04-2008 à 08:08:41
sauf que non ...
les opérateurs synthétisés sont de betes copie bit à bit. Pour des objets avec des pointeurs ou autre joyeusetés, ils sont inopérant.
Ton blabla sur la STL, c'est nimp. vector copie des qu'il copie. On est pas en JAVA ou en je sais pas quoi
Marsh Posté le 29-04-2008 à 14:02:41
mon pauvre Joel, si Taz était la t'en aurais pris plein la gueule, heureusement je n'ai pas son caractère.
tu vas allez relire le standard et revenir quand tu auras compris que le C++ n'est pas du C:
http://www.kuzbass.ru:8086/docs/isocpp/special.html
section 12.8 sous sections -8- et -13-
maintenant a propos du conteneur vector, je te l'accorde, tu as raison.
et cette discussion corrobore les fait:
http://forum.hardware.fr/hfr/Progr [...] 7907_1.htm
pour les string, cela dépend du "vendor". en tout cas, j'admet bien volontier que la vieille SGI (97-99) ne le fait pas, comme indiqué dans ce header:
http://www.sgi.com/tech/stl/string
Code :
|
cependant, il ne faut pas être catégorique comme tu l'es:
http://developers.sun.com/solaris/ [...] l-new.html
a bon entendeur.
Marsh Posté le 29-04-2008 à 14:10:37
mais je suis là. que SGI implémente ses string en faisant du COW, c'est tout à fait secondaire, c'est un détail d'implémentation. je ne comprends pas trop ton excitation: c'est toi qui fait une remarque fausse. il y a pas mal d'implémentation de string qui font du COW, mais ça reste limité comme avantage dans la pratique. et ça ne dispense certainement pas d'implémenter les préconisations de Coplien.
Marsh Posté le 29-04-2008 à 14:39:44
Lightness1024 a écrit : mon pauvre Joel, si Taz était la t'en aurais pris plein la gueule .... |
qu'est-ce qui faut pas entendre ...
Marsh Posté le 30-04-2008 à 11:39:12
Taz a écrit : |
Tu ne m'as toujours pas compris : il n'y a pas de constructeur par copie ni d'opérateur affectation !
J'ai oublié de préciser que ce n'est pas moi qui ai codé le constructeur. En plus, je n'ai pas le droit de toucher à ce constructeur.
Du coup, je ne peux ni ajouter un constructeur copie ni surcharger l'opérateur !
Ce n'est pas mon problème si c'est mal codé ou si ça ne respecte pas la "forme canonique de Coplien", c'est juste que je ne peux pas y remédier par la surcharge ou la copie.
Dans mon objet, il n'y a qu'un constructeur et un destructeur ...
J'ai fait une fonction Copy et désolé Taz, je sais c'est "crade" mais je n'ai pas le choix et ça marche.
La fonction est basée sur le parcours du vector avec un itérateur etc etc ...
Sujet Résolu.
Merci pour votre aide.
Marsh Posté le 30-04-2008 à 12:29:08
LaTex_man a écrit : |
c'est ça l'erreur (c'est véritablement une erreur de programmation/conception).
LaTex_man a écrit : |
Nan mais c'est pas que c'est crade, c'est que c'est cassé, si tu fais ça, tu ne feras pas mieux que ton collègue. Ca n'a pas de sens de mettre ça dans un vector. Mieux vaudrait un vector<MonObjet*>.
Marsh Posté le 30-04-2008 à 16:07:42
Lightness1024 a écrit : mon pauvre Joel, si Taz était la t'en aurais pris plein la gueule, heureusement je n'ai pas son caractère. |
Oui, enfin bon, la "rule of three" n'est pas faite pour les canis lupus domesticus: Si un objet a besoin d'un destructeur autre que le destructeur automatiquement généré par defaut par le compilo, il a tres probablement aussi besoin d'un constructeur par copie, et d'un operateur d'affectation autres que ceux générés par défaut par le compilo. Et comme au vu des commentaires de latex_man, il y a un destructeur explicite pour MonObjet...
A+,
Marsh Posté le 03-05-2008 à 16:31:55
Joel F a écrit : Commandement n°1: |
J'aimerais bien qu'on enterre cette phrase avec celle du "faut pas optimiser" de Knuth...
Si ta classe est simple et bien faite :
- Il y a toutes les chances que le constructeur par défaut généré par le compilateur soit suffisant.
- Ou peut être que le construteur par défaut n'a aucun sens. Ceratins objets ne peuvent être construits qu'avec un minimum de paramètres.
- Il y a toutes les chances que le constructeur de copie généré par le compilateur soit suffisant.
- Il y a toutes les chances que l'operateur= généré par le compilateur soit suffisant.
- Il y a toutes les chances que le destructeur généré par le compilateur soit suffisant. S'il y a un delete dans le destructeur, il faut voir s'il n'est pas possible d'utiliser un std::auto_prt par exemple. Et en plus ça sera exception-safe.
Je rappelle que contrairement au C, la copie (ou la construction par copie) n'est pas une copie bit-a-bit mais une recopie récursive des membres en rappellant leur propre constructeur/operateur de copie. Si la structure/classe est "à la C" (Plain-Old-Data) le compilo va bien sûr faire une copie bi-a-bit, mais c'est de l'optimisation.
L'intéret de laisser le compilo générer ce code est qu'il sera au moins aussi rapide que le votre, et surement moins buggé.
Attention je parle bien des petites classes simples, ici la classe de latex_man a l'air complexe et donc aura surement besoin d'une forme de Coplien.
Mais qd je vois du code dans le style :
class Point |
alors que dans cette petite classe tout ce qui est en rouge est parfaitement inutile, sans compter le destructeur virtuel que certains mettent "pour être sûr" et qui va faire passer la taille de 8 à 12 octets (voire 16 si machine 64 bits), ça me pique les yeux.
Celui qui maitrise son code et qui connait le comportement des membres de sa classe convergera naturellement vers une forme de Coplien sans même s'en rendre compte. Sinon, c'est qu'il n'en a pas besoin, et tant mieux, ça fera du code pourri en moins.
Marsh Posté le 03-05-2008 à 16:56:13
of course que ta classe point a pas besoin de FCC
Pour des classes POD, ca n'a pas grand intérêt ... mais je préfère être lourd, surtout vis à vis pour un PO pas au fait du truc.
Knuth, c'était bien en 1970, mais bon, now, les compilos sont qd même pas des manches.
Edit : pour plus de détails, je pense qu'expliquait les bonnes manières d'abord et les manières rapides ensuite reste une bonne stratégie pédagogique. Sinon tu noies les gens
Marsh Posté le 03-05-2008 à 17:10:36
ok je suis 100% d'accord avec toi
Par contre pour les compilos, il faut pas se reposer trop dessus surtout que leur pouvoir est limité, si tu fais des passages d'objets par valeur dans les parametres, le compilo n'a PAS le droit de faire un passage par ref à ta place. Le standard C++ encadre ce que les compilos ont le droit ou pas de faire. Par contre dans un contexte à la Knuth, donc en assembleur, là en effet de nos jours rares sont les cas où il faut descendre aussi bas. Mais ça veut pas dire qu'on a le droit de tout coder en O(n^42) parce qu'on a de bons compilos et proc. Ca ça sera pour les ordinateurs quantiques, en attendant, il faut garder de bonnes habitudes
Marsh Posté le 03-05-2008 à 18:05:15
jesus_christ a écrit : J'aimerais bien qu'on enterre cette phrase avec celle du "faut pas optimiser" de Knuth... |
Ce serait bien aussi de pas oublier le "prématurément" critique au sens de la phrase
Marsh Posté le 03-05-2008 à 18:53:48
c'était volontaire de ma part, si on suit le principe de Knuth, en pratique :
- Au début on n'optimise pas parce Knuth a dit que c'était pas bien
- Après, on a du code qui "marche et on ne veut plus y toucher", "on n'a pas le temps", et puis "si ça se trouve c'est même pas cette fonction qui pose problème" (expérience inside).
Alors gardez en tête la notion de perf en permanance, vous coderez pas foncièrement moins vite, le code ne sera pas spécialement - lisible (Knuth parlait lui de l'ASM) et votre programme sera globalement + rapide. Surtout qu'en utilisant correctement les bibliothèques, un code optimisé est souvent un code + court et + simple.
Marsh Posté le 03-05-2008 à 18:57:12
jesus_christ a écrit : c'était volontaire de ma part |
Ok, désolé je n'avais pas compris que c'était voulu
Marsh Posté le 05-05-2008 à 17:36:55
jesus_christ a écrit : Celui qui maitrise son code et qui connait le comportement des membres de sa classe convergera naturellement vers une forme de Coplien sans même s'en rendre compte. Sinon, c'est qu'il n'en a pas besoin, et tant mieux, ça fera du code pourri en moins. |
Juste pour vous situer, j'ai une formation de mathématiques appliquées.
J'interviens sur du code déjà implémenté.
Certes, en amont, le codeur s'est dit qu'il n'en avait pas besoin.
Mais, en aval, si ça se trouve, j'en ai besoin.
Du coup, je fais faire au programme ce qu'il n'était pas sensé faire ...
Souvent ça coince d'ailleurs ...
Marsh Posté le 28-04-2008 à 14:35:42
Bonjour à tous,
Je n'ai pas un problème d'exécution mais plutôt de compréhension par rapport aux conteneurs spécialement le vector.
Comportement attendu :
Que le second vector b possède le même contenu que le vector et a et qu'il soit un vector à part entière.
Comportement observé :
Quand j'exécute mon programme, il n'y a pas d'erreur. Par contre, le débugguer a arrêté le programme lorsque je faisais plutard des opérations sur le vector b.
Erreurs : Attempt to take contents of a non pointer value.
Ce problème apparait quand je supprime la tête d'un vector.
Analyse :
Je crois que la copie que je veux n'a pas eu lieu. Je soupçonne le C de m'avoir créer seulement un pointeur sur le vector a et que du coup c'est le même que j'utilise pour mes opérations alors que je veux laisser le vector a de côté et utiliser le vector b.
Solutions possibles :
- Je surcharge l'opérateur "=" dans mon objet
- Utilisation de std::copy
Merci de m'expliquer ce qui se passe exactement et quelle est la meilleure des deux solutions ?
Y en a-t-il d'autres ?