Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
2676 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  [C/C++] Copie d'un std::vector

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[C/C++] Copie d'un std::vector

n°1725645
LaTex_man
Posté le 28-04-2008 à 14:35:42  profilanswer
 

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.

Code :
  1. std::vector<MonObjet> a;
  2. a.push_back(x);
  3. a.push_back(y);
  4. std::vector<MonObjet> b;
  5. b=a;


 
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  

Code :
  1. MonObjet& operator=( const MonObjet )
  2.   {
  3.     ...
  4.     return *this;
  5.   }


 
- 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 ?

mood
Publicité
Posté le 28-04-2008 à 14:35:42  profilanswer
 

n°1725668
Taz
bisounours-codeur
Posté le 28-04-2008 à 15:02:18  profilanswer
 

- 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.

n°1725705
LaTex_man
Posté le 28-04-2008 à 15:57:28  profilanswer
 

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 ...

n°1725715
Taz
bisounours-codeur
Posté le 28-04-2008 à 16:04:37  profilanswer
 

LaTex_man a écrit :

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 ...


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.

n°1725794
Joel F
Real men use unique_ptr
Posté le 28-04-2008 à 18:28:23  profilanswer
 

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

n°1725909
Lightness1​024
Posté le 29-04-2008 à 04:02:55  profilanswer
 

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.


---------------
http://projets.6mablog.com/
n°1725924
Joel F
Real men use unique_ptr
Posté le 29-04-2008 à 08:08:41  profilanswer
 

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 :o

n°1726206
Lightness1​024
Posté le 29-04-2008 à 14:02:41  profilanswer
 

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 :
  1. // it does not perform reference-count or copy-on-write


 
cependant, il ne faut pas être catégorique comme tu l'es:
http://developers.sun.com/solaris/ [...] l-new.html
 
a bon entendeur.


---------------
http://projets.6mablog.com/
n°1726222
Taz
bisounours-codeur
Posté le 29-04-2008 à 14:10:37  profilanswer
 

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.

n°1726272
Joel F
Real men use unique_ptr
Posté le 29-04-2008 à 14:39:44  profilanswer
 

Lightness1024 a écrit :

mon pauvre Joel, si Taz était la t'en aurais pris plein la gueule ....


 
 :sweat: qu'est-ce qui faut pas entendre ...

mood
Publicité
Posté le 29-04-2008 à 14:39:44  profilanswer
 

n°1726797
LaTex_man
Posté le 30-04-2008 à 11:39:12  profilanswer
 

Taz a écrit :


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.


 
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.

Message cité 1 fois
Message édité par LaTex_man le 30-04-2008 à 11:45:40
n°1726825
Taz
bisounours-codeur
Posté le 30-04-2008 à 12:29:08  profilanswer
 

LaTex_man a écrit :


 
Tu ne m'as toujours pas compris : il n'y a pas de constructeur par copie ni d'opérateur affectation !


 
c'est ça l'erreur (c'est véritablement une erreur de programmation/conception).
 

LaTex_man a écrit :


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.


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*>.

n°1726962
gilou
Modérateur
Modzilla
Posté le 30-04-2008 à 16:07:42  profilanswer
 

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.
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-
 
a bon entendeur.

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+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°1727988
jesus_chri​st
votre nouveau dieu
Posté le 03-05-2008 à 16:31:55  profilanswer
 

Joel F a écrit :

Commandement n°1:
"La forme canonique de Coplien pour tes objets tu respecteras"


 
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
{
   Point() : x(0), y(0) {}
[#ff0000]   Point( const Point& p ) x(p.x), y(p.y) {}
   virtual ~Point() {}
   Point& operator=( const Point& p ) { x = p.x; y = p.y; }[/#ff0000]
   // get, set ...
private :
   int x, y;
};


 
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.

n°1728008
Joel F
Real men use unique_ptr
Posté le 03-05-2008 à 16:56:13  profilanswer
 

of course que ta classe point a pas besoin de FCC :o
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


Message édité par Joel F le 03-05-2008 à 16:58:47
n°1728018
jesus_chri​st
votre nouveau dieu
Posté le 03-05-2008 à 17:10:36  profilanswer
 

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 ;)

n°1728037
IrmatDen
Posté le 03-05-2008 à 18:05:15  profilanswer
 

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 ;)

n°1728044
jesus_chri​st
votre nouveau dieu
Posté le 03-05-2008 à 18:53:48  profilanswer
 

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.

n°1728045
IrmatDen
Posté le 03-05-2008 à 18:57:12  profilanswer
 

jesus_christ a écrit :

c'était volontaire de ma part


Ok, désolé je n'avais pas compris que c'était voulu

n°1728724
LaTex_man
Posté le 05-05-2008 à 17:36:55  profilanswer
 

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 ...


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  [C/C++] Copie d'un std::vector

 

Sujets relatifs
[C/C++] Répondre au formulaire d'une page web (+info sur libCurl)Comment lire une image d'un fichier en C++
C# datagridviewcomboboxcolumntuto C++
creation et ecriture dans un fichier en C[C#] Appeller plusieurs méthodes asynchrones ?
PB socket C et fcntl()Probleme sur une macro excel qui ne copie pas tout
[C#] Lecture d'un port USB[Résolu] porté d'une variable vector
Plus de sujets relatifs à : [C/C++] Copie d'un std::vector


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR