¿Cómo puedo hacerlo realloc
en C ++? Parece que falta en el lenguaje - ¡hay new
y delete
pero no resize
!
Lo necesito porque a medida que mi programa lee más datos, necesito reasignar el búfer para contenerlo. No creo que delete
usar el puntero antiguo y new
uno nuevo y más grande sea la opción correcta.
c++
new-operator
realloc
delete-operator
bodacydo
fuente
fuente
Respuestas:
Utilice :: std :: vector!
Type* t = (Type*)malloc(sizeof(Type)*n) memset(t, 0, sizeof(Type)*m)
se convierte en
::std::vector<Type> t(n, 0);
Entonces
t = (Type*)realloc(t, sizeof(Type) * n2);
se convierte en
Si desea pasar el puntero a la función, en lugar de
utilizar
Foo(&t[0])
Es un código C ++ absolutamente correcto, porque el vector es una matriz C inteligente.
fuente
Type* t = static_cast<Type*>(malloc(n * sizeof *t));
t.data()
lugar de&t[0]
La opción correcta es probablemente usar un contenedor que haga el trabajo por usted, como
std::vector
.new
ydelete
no pueden cambiar de tamaño, porque asignan suficiente memoria para contener un objeto del tipo dado. El tamaño de un tipo determinado nunca cambiará. Haynew[]
y,delete[]
pero casi nunca hay una razón para usarlos.Lo que
realloc
hace en C es probable que sea solo unmalloc
,memcpy
yfree
, de todos modos, aunque los administradores de memoria pueden hacer algo inteligente si hay suficiente memoria libre contigua disponible.fuente
std::vector
crecerá automáticamente cuando sea necesario y puede preasignar memoria si lo desea (reserve()
).std::string
, por cierto.)std::string
puedo hacer eso. Por cierto, existe la posibilidad de que su lectura de datos también se pueda simplificar. ¿Cómo estás leyendo tus datos?thevector.resize(previous_size + incoming_size)
, seguido de unmemcpy
(o similar) en&thevector[previous_size]
, es lo que necesita. Se garantiza que los datos del vector se almacenarán "como una matriz".Cambiar el tamaño en C ++ es incómodo debido a la posible necesidad de llamar a constructores y destructores.
No creo que haya una razón fundamental por la cual en C ++ no podrías tener un
resize[]
operador con quien irnew[]
ydelete[]
eso hizo algo similar a esto:newbuf = new Type[newsize]; std::copy_n(oldbuf, std::min(oldsize, newsize), newbuf); delete[] oldbuf; return newbuf;
Obviamente
oldsize
, se recuperaría de una ubicación secreta, en la misma ubicacióndelete[]
, yType
vendría del tipo de operando.resize[]
fallaría si el tipo no se puede copiar, lo cual es correcto, ya que estos objetos simplemente no se pueden reubicar. Finalmente, el código anterior construye por defecto los objetos antes de asignarlos, lo que no querría como comportamiento real.Hay una posible optimización en la que
newsize <= oldsize
, para llamar a los destructores de los objetos "más allá del final" de la matriz recién ensmallened y no hacer nada más. El estándar tendría que definir si esta optimización es necesaria (como cuando se trata deresize()
un vector), permitida pero no especificada, permitida pero dependiente de la implementación o prohibida.La pregunta que debería hacerse es, "¿es realmente útil proporcionar esto, dado que
vector
también lo hace, y está diseñado específicamente para proporcionar un contenedor que se puede cambiar de tamaño (de memoria contigua? Ese requisito se omite en C ++ 98 pero arreglado en C ++ 03) que se ajusta mejor que las matrices con las formas de hacer las cosas de C ++? "Creo que la respuesta es generalmente "no". Si desea hacer búferes redimensionables a la manera de C, use
malloc / free / realloc
, que están disponibles en C ++. Si desea hacer búferes redimensionables a la manera de C ++, use un vector (odeque
, si en realidad no necesita almacenamiento contiguo). No intente mezclar los dos utilizandonew[]
para búferes sin formato, a menos que esté implementando un contenedor similar a un vector.fuente
Aquí hay un ejemplo de std :: move que implementa un vector simple con un realloc (* 2 cada vez que llegamos al límite). Si hay una manera de hacerlo mejor que la copia que tengo a continuación, hágamelo saber.
Compilar como:
g++ -std=c++2a -O2 -Wall -pedantic foo.cpp
Código:
#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); }
fuente
prueba algo como eso:
typedef struct Board { string name; int size = 0; }; typedef struct tagRDATA { vector <Board> myBoards(255); // Board DataBoard[255]; int SelectedBoard; } RUNDATA;
Vector se quejará. Es por eso que aún existen arrays, malloc y new.
fuente
typedef
en todas partes como si estuviera escribiendo C