Wie kann ich realloc
in C ++? Es scheint in der Sprache zu fehlen - es gibt new
und delete
aber nicht resize
!
Ich brauche es, weil mein Programm, wenn es mehr Daten liest, den Puffer neu zuweisen muss, um es zu halten. Ich denke nicht, dass es die richtige Option ist, den delete
alten Zeiger und new
einen neuen, größeren Zeiger zu verwenden .
c++
new-operator
realloc
delete-operator
bodacydo
quelle
quelle
Antworten:
Verwenden Sie :: std :: vector!
Type* t = (Type*)malloc(sizeof(Type)*n) memset(t, 0, sizeof(Type)*m)
wird
::std::vector<Type> t(n, 0);
Dann
t = (Type*)realloc(t, sizeof(Type) * n2);
wird
Wenn Sie den Zeiger anstelle der Funktion an die Funktion übergeben möchten
verwenden
Foo(&t[0])
Es ist absolut korrekter C ++ - Code, da der Vektor ein intelligentes C-Array ist.
quelle
Type* t = static_cast<Type*>(malloc(n * sizeof *t));
t.data()
anstelle von&t[0]
Die richtige Option ist wahrscheinlich, einen Container zu verwenden, der die Arbeit für Sie erledigt, wie z
std::vector
.new
unddelete
können die Größe nicht ändern, da sie gerade genug Speicher zuweisen, um ein Objekt des angegebenen Typs aufzunehmen. Die Größe eines bestimmten Typs wird sich nie ändern. Es gibtnew[]
unddelete[]
aber es gibt kaum einen Grund, sie zu benutzen.Was
realloc
in C funktioniert, ist wahrscheinlich nur einmalloc
,memcpy
und auffree
jeden Fall , obwohl Speichermanager etwas Kluges tun dürfen, wenn genügend zusammenhängender freier Speicher verfügbar ist.quelle
std::vector
sondern verwenden Sie ihn einfach - er wächst bei Bedarf automatisch und Sie können Speicher vorab zuweisen, wenn Sie möchten (reserve()
).std::string
übrigens auch.)std::string
kann das tun. Übrigens besteht die Möglichkeit, dass auch das Lesen Ihrer Daten vereinfacht wird. Wie lesen Sie Ihre Daten?thevector.resize(previous_size + incoming_size)
, gefolgt von einemmemcpy
(oder ähnlichen) in&thevector[previous_size]
, ist das, was Sie brauchen. Die Daten des Vektors werden garantiert "wie ein Array" gespeichert.Die Größenänderung in C ++ ist umständlich, da möglicherweise Konstruktoren und Destruktoren aufgerufen werden müssen.
Ich glaube nicht, dass es einen fundamentalen Grund gibt, warum Sie in C ++ keinen
resize[]
Operator haben könnten,new[]
unddelete[]
das hat etwas Ähnliches bewirkt:newbuf = new Type[newsize]; std::copy_n(oldbuf, std::min(oldsize, newsize), newbuf); delete[] oldbuf; return newbuf;
Offensichtlich
oldsize
würde von einem geheimen Ort abgerufen werden, genauso wie es istdelete[]
, undType
würde vom Typ des Operanden kommen.resize[]
würde fehlschlagen, wenn der Typ nicht kopierbar ist - was richtig ist, da solche Objekte einfach nicht verschoben werden können. Schließlich konstruiert der obige Code die Objekte standardmäßig, bevor sie zugewiesen werden, was Sie nicht als tatsächliches Verhalten wünschen würden.Es gibt eine mögliche Optimierung
newsize <= oldsize
, bei der Destruktoren für die Objekte "nach dem Ende" des neu zusammengestellten Arrays aufgerufen werden und nichts anderes getan wird. Der Standard müsste definieren, ob diese Optimierung erforderlich ist (wie beiresize()
einem Vektor), zulässig, aber nicht spezifiziert, zulässig, aber implementierungsabhängig oder verboten.Die Frage, die Sie sich dann stellen sollten, lautet: "Ist es tatsächlich nützlich, dies bereitzustellen, da dies
vector
auch der Fall ist, und wurde speziell entwickelt, um einen Container mit veränderbarer Größe (mit zusammenhängendem Speicher - diese Anforderung wurde in C ++ 98 jedoch weggelassen) bereitzustellen." behoben in C ++ 03) passt das besser als Arrays zu den C ++ - Methoden? "Ich denke, die Antwort wird allgemein als "nein" angesehen. Wenn Sie anpassbare Puffer auf C-Weise erstellen möchten, verwenden Sie diese
malloc / free / realloc
, die in C ++ verfügbar sind. Wenn Sie die Größe von Puffern in C ++ ändern möchten, verwenden Sie einen Vektor (oderdeque
, wenn Sie keinen zusammenhängenden Speicher benötigen). Versuchen Sie nicht, beide mithilfe von Rohpuffern zu mischennew[]
, es sei denn, Sie implementieren einen vektorähnlichen Container.quelle
Hier ist ein Beispiel für std :: move, das einen einfachen Vektor mit einem Realloc implementiert (* 2 jedes Mal, wenn wir das Limit erreichen). Wenn es einen Weg gibt, es besser zu machen als die Kopie, die ich unten habe, lassen Sie es mich bitte wissen.
Kompilieren als:
g++ -std=c++2a -O2 -Wall -pedantic foo.cpp
Code:
#include <iostream> #include <algorithm> template<class T> class MyVector { private: T *data; size_t maxlen; size_t currlen; public: MyVector<T> () : data (nullptr), maxlen(0), currlen(0) { } MyVector<T> (int maxlen) : data (new T [maxlen]), maxlen(maxlen), currlen(0) { } MyVector<T> (const MyVector& o) { std::cout << "copy ctor called" << std::endl; data = new T [o.maxlen]; maxlen = o.maxlen; currlen = o.currlen; std::copy(o.data, o.data + o.maxlen, data); } MyVector<T> (const MyVector<T>&& o) { std::cout << "move ctor called" << std::endl; data = o.data; maxlen = o.maxlen; currlen = o.currlen; } void push_back (const T& i) { if (currlen >= maxlen) { maxlen *= 2; auto newdata = new T [maxlen]; std::copy(data, data + currlen, newdata); if (data) { delete[] data; } data = newdata; } data[currlen++] = i; } friend std::ostream& operator<<(std::ostream &os, const MyVector<T>& o) { auto s = o.data; auto e = o.data + o.currlen;; while (s < e) { os << "[" << *s << "]"; s++; } return os; } }; int main() { auto c = new MyVector<int>(1); c->push_back(10); c->push_back(11); }
quelle
versuchen Sie so etwas:
typedef struct Board { string name; int size = 0; }; typedef struct tagRDATA { vector <Board> myBoards(255); // Board DataBoard[255]; int SelectedBoard; } RUNDATA;
Vector wird sich beschweren. Deshalb gibt es immer noch Arrays, Malloc und New.
quelle
typedef
überall verwenden, als ob Sie C schreiben würden.