genre ptr = ptr + nouvelle_adresse - ancienne_adresse.
ça m’étonnerait pas que ça soit un UB (arithmétique de pointeurs avec des objets qui ne sont pas du même "bloc").
Théoriquement c’est pas faux… mais en pratique je ne vois pas pourqoi ça ne marcherait pas, au pire avec un cast en int64_t pour être sûr qu’il n’y aura pas de débordement.
Ceci dit je peux toujours le réécrire ptr = nouvelle_adresse + (ptr - ancienne_adresse)
, et là plus aucun risque normalement (vu qu’on a pointeur + (pointeur - pointeur)
= pointeur + entier
).
De toute façon je ne suis plus à un UB près, j’ai déjà du code très borderline à certains endroits, et bien pire que ça… genre cast de pointeur de fonction, union possédant des méthodes, placement new/delete/new[]/delete[], …
Je suppose que garder une référence sur le vecteur + une position n’irait pas non plus ? Comment fais-tu pour garantir que la pile existe toujours ?
Avec une référence sur le vecteur + une position, j’ai aussi essayé, mais je n’ai pas réussi, car j’ai l’impression que je ne sais pas toujours vraiment de quelle fil vient un pointeur donné. Par contre pour l’existance de la pile je n’ai rien à craindre.
L’upvalue peut être dans deux états: ouverte ou fermée. Tant qu’on est dans le scope elle est ouverte et elle pointe dans la pile. Dès qu’on quitte le scope, ce qui correspond aussi au moment où on dépile la valeur, l’upvalue est fermée, c’est-à-dire qu’on prend sa valeur actuelle et on va la stocker ailleurs en-dehors de toute pile d’exécution. Donc on n’a jamais de valeur qui n’existe plus.
Après le seul moyen de savoir exactement quand il y a une nouvelle allocation est de remplacer l’allocateur du conteneur par un qui implémente une fonction
allocate pour faire un système de signaux. Il faudrait aussi regarder la doc pour savoir quels sont les types membres à ajouter pour qu’il fonctionne bien
dans ton cas. Tout ce qui n’est pas implémenté utilise implicitement le comportement par défaut (voir std::allocator_traits).
Je vais aller voir de ce côté-ci, merci. JE n’ai encore jamais utilisé d’allocateur.
Après, tu peux utiliser autre chose que vector comme une liste de tableau de 64 entrés (ou plus) ou un vector de unique_ptr<T[n]>. Ainsi, une nouvelle
allocation n’invalide pas l’ancienne, mais c’est un peu plus difficile à manipuler.
std::unique_ptr<T[n]>
? Il n’y a pas de std::unique_array et pas de risque de conflit entre new/delete et new[]/delete[] ?
Cela dit je ne suis pas sûr que ça résoudrais mon problème, car ça voudrait dire que je ne pointe plus forcément toujours sur la dernière valeur, ce qui ne va pas non plus.
JE viens de tomber sur boost::stable_vector, je suis en train de me demander si ça ne résoudrait pas mon problème en fait; mais on dirait que le déficit de performances est quand même assez important d’après ce qu’ils en disent.