Como posso realloc
em C ++? Parece faltar na linguagem - existe new
e delete
não existe resize
!
Eu preciso disso porque, à medida que meu programa lê mais dados, preciso realocar o buffer para mantê-los. Não acho que delete
o ponteiro antigo e o new
novo, maior, sejam a opção certa.
c++
new-operator
realloc
delete-operator
bodacydo
fonte
fonte
Respostas:
Use :: std :: vector!
Type* t = (Type*)malloc(sizeof(Type)*n) memset(t, 0, sizeof(Type)*m)
torna-se
::std::vector<Type> t(n, 0);
Então
t = (Type*)realloc(t, sizeof(Type) * n2);
torna-se
Se você quiser passar o ponteiro para a função, em vez de
usar
Foo(&t[0])
É um código C ++ absolutamente correto, porque vetor é um array C inteligente.
fonte
Type* t = static_cast<Type*>(malloc(n * sizeof *t));
t.data()
vez de&t[0]
A opção certa é provavelmente usar um contêiner que faça o trabalho para você, como
std::vector
.new
edelete
não podem ser redimensionados, porque alocam apenas memória suficiente para armazenar um objeto de um determinado tipo. O tamanho de um determinado tipo nunca mudará. Hánew[]
edelete[]
dificilmente há uma razão para usá-los.O que
realloc
significa em C provavelmente será apenas ummalloc
,memcpy
efree
, de qualquer maneira, embora os gerenciadores de memória possam fazer algo inteligente se houver memória livre contígua suficiente disponível.fonte
std::vector
- ele aumentará automaticamente quando necessário e você pode pré-alocar memória se quiser (reserve()
).std::string
propósito, também pode .)std::string
pode fazer isso. A propósito, há uma chance de que a leitura de seus dados também possa ser simplificada. Como você está lendo seus dados?thevector.resize(previous_size + incoming_size)
, seguido pormemcpy
(ou semelhante) em&thevector[previous_size]
, é o que você precisa. Os dados do vetor são armazenados "como uma matriz".O redimensionamento em C ++ é estranho devido à necessidade potencial de chamar construtores e destruidores.
Não acho que haja uma razão fundamental pela qual em C ++ você não poderia ter um
resize[]
operador para acompanharnew[]
edelete[]
, isso fez algo semelhante a isto:newbuf = new Type[newsize]; std::copy_n(oldbuf, std::min(oldsize, newsize), newbuf); delete[] oldbuf; return newbuf;
Obviamente,
oldsize
seria recuperado de um local secreto, mesmo que estivessedelete[]
, eType
viria do tipo do operando.resize[]
falharia onde o tipo não é copiável - o que é correto, uma vez que tais objetos simplesmente não podem ser realocados. Finalmente, o código acima constrói os objetos por padrão antes de atribuí-los, o que você não gostaria que fosse o comportamento real.Há uma possível otimização em
newsize <= oldsize
que chamar destruidores para os objetos "além do final" do array recém-formado e não fazer mais nada. O padrão teria que definir se essa otimização é necessária (como quando vocêresize()
usa um vetor), permitida mas não especificada, permitida mas dependente da implementação ou proibida.A pergunta que você deve fazer a si mesmo é: "é realmente útil fornecer isso, visto que
vector
também o faz, e é projetado especificamente para fornecer um contêiner redimensionável (de memória contígua - esse requisito omitido em C ++ 98, mas corrigido em C ++ 03) é um ajuste melhor do que arrays com as formas de C ++ de fazer as coisas? "Acho que a resposta é amplamente considerada "não". Se você quiser fazer buffers redimensionáveis à maneira C, use
malloc / free / realloc
, que estão disponíveis em C ++. Se você quiser fazer buffers redimensionáveis da maneira C ++, use um vetor (oudeque
, se você realmente não precisa de armazenamento contíguo). Não tente misturar os dois usandonew[]
buffers brutos, a menos que esteja implementando um contêiner semelhante a um vetor.fonte
Aqui está um exemplo std :: move implementando um vetor simples com um realloc (* 2 cada vez que atingimos o limite). Se houver uma maneira de fazer melhor do que a cópia que tenho abaixo, por favor, me avise.
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); }
fonte
tente algo assim:
typedef struct Board { string name; int size = 0; }; typedef struct tagRDATA { vector <Board> myBoards(255); // Board DataBoard[255]; int SelectedBoard; } RUNDATA;
Vector vai reclamar. É por isso que arrays, malloc e new ainda existem.
fonte
typedef
todos os lugares como se estivesse escrevendo C.