Compilation bizarre avec VS.NET... - C++ - Programmation
Marsh Posté le 05-10-2002 à 00:08:17
sans le "const" et l'inline de la déclaration operator T* ()
Code :
|
le compilo fait la même chose....
Marsh Posté le 05-10-2002 à 00:21:28
et les formes:
Code :
|
chient autant (ça aurait pu être une subtilité operator T* () / operator [] (int i) )
par contre idem les formes MARCHENT:
Code :
|
toujours en DEBUG... (compilation boeuf)
en fait ce con utilise l'operator T*() trop tôt.....
debug ASM pour Strip &CStrip = Strips[ Strips.Alloc() ];
Code :
|
et idem pour la forme Strip &CStrip = *(Strips.Alloc() + Strips);
Code :
|
Marsh Posté le 05-10-2002 à 00:57:00
Bon bin autant pour moi, ça doit être défini dans la norme ANSI, Borland C++ Builder 6 fait la même chose
Marsh Posté le 05-10-2002 à 01:42:58
Ajoute dans ta classe rvector
Code :
|
Autrement le compilo transforme
Strips[ Strips.Alloc() ]
en, comme tu l'as écrit,:
*(Strips + Strips.Alloc())
(et dans ce cas, le comportement est celui attendu)
Marsh Posté le 05-10-2002 à 04:14:26
Les compilateurs sont libres d'évaluer les opérandes d'une expresion dans l'ordre qu'ils veulent (standard C/C++).
Exceptions: || && ?: (contrôle de flux)
Donc, ces codes ont des comportements dépendants du compilateur:
Code :
|
Je pense que rvector::Alloc devrait renvoyer un pointeur (ou référence) sur l'élément alloué.
Code :
|
Mais es-tu sûr de faire mieux qu'un conteneur STL ?
Code :
|
Marsh Posté le 05-10-2002 à 11:08:36
oui le vector passe par new/delete...
en fait si tu as un tableau de 256 mo de capcité alloué, et quand tu arrives au bout de la capacité, il:
1) crée un tableau de la nouvelle taille (pour 256 mo d'objets + le delta qu'il se donne)
2) recopie l'ancien tableau dans le nouveau
3) supprimme l'ancien.
ce qui fait que l'occupation mémoire crête au moment de l'agrandissement est 2x la taille utile...
et le cpu se bouffe la recopie....
y'a les listes & co..., mais dans certains cas je prèfère une collection en tableau, qu'en liste chaine ou autre, c'est plus efficace au niveau cache cpu....
histoire de compenser ça, la seule technique qu'ils ont trouvés, c'est foutre un gros delta....
Marsh Posté le 05-10-2002 à 11:10:01
verdoux a écrit a écrit : Ajoute dans ta classe rvector
|
oui mais si j'ai les deux l'operator T* (), l'operator T operator [](int i), le compilo gueule passque y'a deux possibilitées ambigues....
Marsh Posté le 05-10-2002 à 11:12:09
enfin c po grave, comme ça se comporte pareil avec le C++ builder 6, je vais passer par un int temporaire....
pour Alloc(), je préfère garder l'indice que l'adresse effective qui peut bouger....
Marsh Posté le 06-10-2002 à 02:06:20
Citation : histoire de compenser ça, la seule technique qu'ils ont trouvés, c'est foutre un gros delta.... |
Ben oui... y'a malheureusement pas 36 façons de redimensionner un conteneur contigü...
La STL peut être implémentée avec utilisation de realloc, pour autant que je sache.
Au niveau le plus simple, on joue au devin avec vector::reserve().
Au niveau complexe, on s'intéresse au paramètre allocator des patrons conteneurs (c'est pas de la tarte).
Marsh Posté le 06-10-2002 à 10:36:47
vi tout à fait, je me doutais que y'avais moyen d'y arriver par les allocators, mais quand je vois comment les Docs C++ sont foutues, j'ai fait au revoir...
sinon y'a une raison simple pour laquelle ils ont pas utilisés le realloc(), et que j'ai tout de suite pris en considération, comme le realloc peut bouger l'adresse de base du tableau, si l'objet A mis en vector va mettre sa propre adresse dans un autre objet B (via les constructeurs et le destructeur), et que l'addresse de l'objet A bouge à cause d'un realloc(), le pointeur de B est foiré...
donc dans la pure logique c++, un vector qui utilise realloc() peut être dangereux si y'a des pointeurs croisés de partout....
mais un fois que tu le sais, tu fais attention à ce que tu mets dans un vector<> qui utilise realloc().
Marsh Posté le 06-10-2002 à 10:40:43
Musaran a écrit a écrit :
Ben oui... y'a malheureusement pas 36 façons de redimensionner un conteneur contigü... |
par contre y'a un truc que j'ai pas analysé, c'est comment vector<> se comportait lorsque l'on mets une grande quatitée d'objet et qu'on les libère....
passke dans mon rvector<>, je realloc pour libérer de la mémoire à l'os quand la capacité-size > 2*delta lors des supressions.
sinon c'est génial le placement new....
Marsh Posté le 07-10-2002 à 02:59:28
Le standard du C++ spécifie bien que l'agrandissement d'un conteneur comme vector peut rendre tous les itérateurs/pointeurs invalides.
Pour cette raison, les conteneurs contigüs ne libèrent pas la mémoire qu'ils s'octroient. Le seul moyen, c'est de le supprimer.
Ils n'ont pas trouvé de solution simple et efficace à cela. C'est mon plus grand reproche à vector: forcément dynamique.
J'ai un trou pour le placement new.
Il n'a pas de delete (individuel) correspondant, et on est responsable de l'appel des destructeurs, c'est bien ça ?
Marsh Posté le 07-10-2002 à 09:33:15
oui, que je realloc(), je fais un placement new() sur les objets alloués, et je fais un ~T() explicite pour les destructions...
Marsh Posté le 04-10-2002 à 23:52:09
voilà j'ai un système de template du style:
c'est une template qui maintiens une collection d'objet (style vector<> de la STL, mais en mieux selon mes critères de performances, les allocations mémoire crêtes sont limitées par un realloc()+placement new)
Alloc() alloue un objet en plus dans la collection (DATA peut bouger), et retourne l'indice dans le tableau du nouvel objet.
operator T* me retourne Data, pour utiliser [] & co....
--------------------------
j'ai un comportement que je trouve anormal avec visual studio .NET:
j'ai un rvector<Strip> Strips;
et à un moment je fais:
Je compile en DEBUG, pas d'optimisations.
Donc on a CSTrip qui maintiens un nouvel objet par adresse.
Strips.Alloc() crée le nouvel objet.
Dans ce cas Data à l'intérieur de la template (dumoins Strips), est bougé par Alloc().
Hors le compilateur semble générer du code tel que l'ancien Data est utilisé pour Strips[ ], et non le nouveau modifié par Alloc().
En gros, quand le compilo bouffe le Strips[ Strips.Alloc() ], il:
1) Prends le Data via l'opérateur T*
2) Effectue Alloc() et retourne l'indice du nouvel objet
3) Alloc modifie Data de Strips
4) l'objet pointé par CStrip est ANCIEN DATA[ indice d'alloc() ]
Ce qui fait que évidemment, ça chie.
si je contourne le comportement du compilateur, par un:
int ind=Strips.Alloc();
Strip &CStrip=Strips[ind];
ça marche....
alors est-ce normal que le compilo utilise d'abord l'operator T*() avant Alloc()
ou alors est-ce dû au fait qu'il y a des truc bizarres dû au fait que ce soit une template à la base
je peux contourner le problème, mais j'aimerais comprendre....