web-dev-qa-db-fra.com

Comment «réallouer» en C ++?

Comment puis-je realloc en C++? Il semble manquer dans la langue - il y a new et delete mais pas resize!

J'en ai besoin car comme mon programme lit plus de données, j'ai besoin de réallouer le tampon pour le contenir. Je ne pense pas que deleteing l'ancien pointeur et newing un nouveau, plus grand, soit la bonne option.

77
bodacydo

Utilisez :: std :: vector!

Type* t = (Type*)malloc(sizeof(Type)*n) 
memset(t, 0, sizeof(Type)*m)

devient

::std::vector<Type> t(n, 0);

Ensuite

t = (Type*)realloc(t, sizeof(Type) * n2);

devient

t.resize(n2);

Si vous voulez passer le pointeur dans la fonction, au lieu de

Foo(t)

utilisation

Foo(&t[0])

C'est un code C++ absolument correct, car vector est un tableau C intelligent.

47
f0b0s

La bonne option est probablement d'utiliser un conteneur qui fait le travail pour vous, comme std::vector.

new et delete ne peuvent pas être redimensionnés, car ils allouent juste assez de mémoire pour contenir un objet du type donné. La taille d'un type donné ne changera jamais. Il y a new[] et delete[] mais il n'y a presque jamais de raison de les utiliser.

Ce que realloc fait en C n'est probablement qu'un malloc, memcpy et free, de toute façon, bien que les gestionnaires de mémoire soient autorisés à faire quelque chose d'intelligent s'il y a est suffisamment de mémoire libre contiguë disponible.

45
Thomas

Le redimensionnement en C++ est gênant en raison du besoin potentiel d'appeler des constructeurs et des destructeurs.

Je ne pense pas qu'il y ait une raison fondamentale pour laquelle en C++ vous ne pouviez pas avoir d'opérateur resize[] Pour aller avec new[] Et delete[], Cela faisait quelque chose de similaire à ceci:

newbuf = new Type[newsize];
std::copy_n(oldbuf, std::min(oldsize, newsize), newbuf);
delete[] oldbuf;
return newbuf;

Évidemment, oldsize serait récupéré à partir d'un emplacement secret, de la même façon qu'il est dans delete[], Et Type proviendrait du type de l'opérande. resize[] Échouerait lorsque le type n'est pas copiable - ce qui est correct, car de tels objets ne peuvent tout simplement pas être déplacés. Enfin, le code ci-dessus construit par défaut les objets avant de les affecter, ce que vous ne voudriez pas comme comportement réel.

Il y a une optimisation possible où newsize <= oldsize, Pour appeler des destructeurs pour les objets "après la fin" du tableau nouvellement réduit et ne rien faire d'autre. La norme devrait définir si cette optimisation est requise (comme lorsque vous resize() un vecteur), autorisée mais non spécifiée, autorisée mais dépendante de l'implémentation, ou interdite.

La question que vous devez alors vous poser est: "est-il réellement utile de fournir cela, étant donné que vector le fait également, et est conçu spécifiquement pour fournir un conteneur redimensionnable (de mémoire contiguë - cette exigence omise en C++ 98 mais corrigé en C++ 03) qui est mieux adapté que les tableaux avec les façons de faire C++? "

Je pense que la réponse est largement considérée comme "non". Si vous voulez faire des tampons redimensionnables à la manière C, utilisez malloc / free / realloc, Qui sont disponibles en C++. Si vous voulez faire des tampons redimensionnables de la manière C++, utilisez un vecteur (ou deque, si vous n'avez pas réellement besoin de stockage contigu). N'essayez pas de mélanger les deux en utilisant new[] Pour les tampons bruts, sauf si vous implémentez un conteneur de type vectoriel.

33
Steve Jessop