C ++: nova chamada que se comporta como calloc?
-
03-07-2019 - |
Pergunta
Existe uma chamada que eu posso fazer para new
para tê-lo zerar memória como calloc
?
Solução
Ao contrário do que alguns estão dizendo em suas respostas, ele é possível.
char * c = new char[N]();
irá zerar inicializar todos os personagens (na realidade, ele é chamado de valor de inicialização. Mas o valor-inicialização vai ser zero-inicialização para todos os seus membros de uma matriz do tipo escalar). Se é isso que você está depois.
Vale a pena notar que ele faz também trabalho para (matrizes de) classe-Tipos sem usuário declarou construtor caso em que qualquer membro deles é o valor inicializado:
struct T { int a; };
T *t = new T[1]();
assert(t[0].a == 0);
delete[] t;
Não é uma extensão ou algo assim. Ele trabalhou e se comportou da mesma maneira em C ++ 98 também. Apenas não foi chamado inicialização padrão em vez de inicialização valor. inicialização de zero, no entanto, é feito em ambos os casos para escalares ou matrizes de escalar ou tipos POD.
Outras dicas
Não, mas é bastante fácil para criar uma nova versão que age como calloc. Isso pode ser feito da mesma maneira que a versão não-lance de novo é implementado.
SomeFile.h
struct zeromemory_t{};
extern const zeromemory_t zeromemory;
void* __cdcel operator new(size_t cbSize, const zeromemory_t&);
SomeFile.cpp
const zeromemory_t zeromemory;
void* _cdecl operator new(size_t cbSize, const zeromemory_t&)
{
void *mem = ::operator new(cbSize);
memset(mem,0,cbSize);
return mem;
}
Agora você pode fazer o seguinte para obter novo com a memória zero'd
MyType* pMyType = new (zeromemory) MyType();
Além disso você precisa fazer outras coisas divertidas como definir novos [] que é bastante para a frente também.
No. Também nem sequer pensar em fazer algo como:
YourClass *var = new YourClass;
memset(var, 0, sizeof(YourClass));
Você pode acabar destruindo seu VTABLE (se sua classe tem um).
Eu recomendaria usar construtores para limpar a memória interna (variáveis) de sua classe.
Não. Será sempre o padrão-inicializar o item alocada (s), que no caso de primitivas não faz nada. Você vai ter que segui-lo com uma chamada std :: uninitialized_fill_n ou similar.
Você poderia fazer uma sobrecarga global new
operador e tê-lo pegar a memória cru de calloc()
. Desta forma, a memória é eliminada antes de construtores começar a correr assim não há não há problemas.
Qualquer classe que substitui novas por si só não vai ter o seu calloc()
especial à base de new
, mas depois que a classe deve ser inicializar-se corretamente de qualquer maneira.
Não se esqueça de substituir tanto new
e delete
e as versões de matriz ...
Algo como:
#include <exception> // for std::bad_alloc
#include <new>
#include <stdlib.h> // for calloc() and free()
void* operator new (size_t size)
{
void *p=calloc(size, 1);
if (p==0) // did allocation succeed?
throw std::bad_alloc();
return p;
}
void operator delete (void *p)
{
free(p);
}
void* operator new[] (size_t size)
{
void *p=calloc(size, 1);
if (p==0) // did allocation succeed?
throw std::bad_alloc();
return p;
}
void operator delete[] (void *p)
{
free(p);
}
Note que essas versões simples não são completamente exatamente o que deveria ser - o operador new
deve ser executado em um loop chamando o new_handler
(se estiver instalado) e apenas lançar a exceção bad_alloc
se não houver new_handler
. Ou algo assim, eu vou ter que procurá-lo e atualização mais tarde.
Ah, e você também pode querer substituir a versão no_throw
também.
i usar uma macro:
#define newclear(TYPE) new(calloc(sizeof(TYPE), 1)) TYPE();
usá-lo:
Whatever* myWhatever = newclear(Whatever);
(Isto usa "colocação novos" como algumas outras soluções aqui)
No.You Tem a zero manualmente a memória fora. Lembre-se, new
não é apenas sobre a alocação de memória, mas também sobre a inicialização através de construtores. Este é o lugar onde calloc
é útil em C (que não tem initializer funções). Você é livre para escrever um wrapper sobre new
ou mesmo calloc
uso, mas na maioria das vezes para não-POD objetos isso não faz muito sentido.
Se você não insistir usando new
, você pode simplesmente usar vetor:. vector<char> buffer; buffer.resize(newsize);
eo conteúdo será zerado
class MyClass {
public:
void* operator new(size_t bytes) {
return calloc(bytes, 1);
}
}
E você pode substituir o novo operador global se você gosta.
Você pode dizer:
vector <char> v( 100, 0 );
que cria um array contíguo de 100 caracteres usando nova, e inicializa-los todos para zero. Você pode, então, acessar a matriz com o operador do vetor [], ou fazendo:
char * p = &v[0];
p[3] = 42;
Observe isso também libera de ter que chamar delete para liberar a memória alocada.
Sim.
int* p_scalar = new int(5);//Does not create 5 elements, but initializes to 5
Para arrays você pode usar algo como memset. Para Windows usar ZeroMemory ou SecureZeroMemory.
Editar:. Por favor, ver @ post de litb, ele mostra como você pode inicializar a 0 para arrays usando inicialização não direta como acima