Domanda

È possibile effettuare una chiamata a new per azzerare la memoria come calloc?

È stato utile?

Soluzione

Contrariamente a quanto dicono alcuni nelle loro risposte, è possibile.

char * c = new char[N]();

Zero inizializzerà tutti i caratteri (in realtà, si chiama inizializzazione del valore. Ma l'inizializzazione del valore sarà l'inizializzazione zero per tutti i suoi membri di un array di tipo scalare). Se è quello che stai cercando.

Vale la pena notare che funziona anche per (matrici di) tipi di classe senza costruttore dichiarato dall'utente, nel qual caso a qualsiasi membro di essi viene inizializzato un valore:

struct T { int a; };
T *t = new T[1]();
assert(t[0].a == 0);
delete[] t;

Non è un'estensione o qualcosa del genere. Ha funzionato e si è comportato allo stesso modo anche in C ++ 98. Proprio lì si chiamava inizializzazione predefinita anziché inizializzazione del valore. L'inizializzazione zero, tuttavia, viene eseguita in entrambi i casi per scalari o array di tipi scalari o POD.

Altri suggerimenti

No, ma è abbastanza facile creare una nuova versione che si comporta come calloc. Può essere fatto più o meno allo stesso modo in cui viene implementata la versione no-throw di new.

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;
}

Ora puoi fare quanto segue per ottenere nuovi con memoria a zero

MyType* pMyType = new (zeromemory) MyType();

Inoltre dovresti fare altre cose divertenti come definire new [] che è anche abbastanza semplice.

No. Inoltre, non pensare nemmeno di fare qualcosa del tipo:

YourClass *var = new YourClass;
memset(var, 0, sizeof(YourClass));

Potresti finire per distruggere il tuo VTABLE (se la tua classe ne ha uno).

Consiglierei di usare i costruttori per cancellare la memoria interna (variabili) della tua classe.

No. Inizializzerà sempre per default gli oggetti allocati, che nel caso delle primitive non fanno nulla. Dovrai seguirlo con una chiamata std :: uninitialized_fill_n o simile.

Potresti fare un sovraccarico globale dell'operatore new e fargli prendere la memoria grezza da calloc(). In questo modo la memoria viene cancellata prima che i costruttori inizino a funzionare, quindi non ci sono problemi.

Qualsiasi classe che sostituisce la nuova da sola non otterrà la tua delete basata su new_handler, ma poi quella classe dovrebbe inizializzarsi correttamente comunque.

Non dimenticare di sostituire sia bad_alloc che no_throw e le versioni dell'array ...

Qualcosa del tipo:

#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); 
}

Nota che queste semplici versioni non sono esattamente come dovrebbero essere: l'operatore <=> dovrebbe essere eseguito in un ciclo chiamando <=> (se installato) e lanciando l'eccezione <=> solo se c'è no <=>. O qualcosa del genere, dovrò cercarlo e aggiornarlo più tardi.

Oh, e potresti voler sostituire anche la <=> versione.

Uso una macro:

#define newclear(TYPE) new(calloc(sizeof(TYPE), 1)) TYPE();

per usarlo:

Whatever* myWhatever = newclear(Whatever);

(utilizza " posizionamento nuovo " come alcune altre soluzioni qui)

No. È necessario azzerare manualmente la memoria. Ricorda, new non si tratta solo di allocare memoria, ma anche di inizializzare tramite i costruttori. Qui è dove calloc è utile in C (che non ha funzioni di inizializzazione). Sei libero di scrivere un wrapper su <=> o persino di usare <=>, ma la maggior parte delle volte per oggetti non POD questo non ha molto senso.

se non insisti nell'uso di new, puoi semplicemente usare il vettore: vector<char> buffer; buffer.resize(newsize); e il contenuto verrà azzerato.

class MyClass {
    public:
    void* operator new(size_t bytes) {
        return calloc(bytes, 1);
    }
}

E puoi ignorare il nuovo operatore globale, se lo desideri.

Puoi dire:

vector <char> v( 100, 0 );

che crea un array contiguo di 100 caratteri usando new e li inizializza a zero. È quindi possibile accedere all'array con l'operatore [] di vector oppure eseguendo:

char * p = &v[0];
p[3] = 42;

Nota che questo ti libera anche dal dover chiamare delete per liberare la memoria allocata.

Sì.

int* p_scalar = new int(5);//Does not create 5 elements, but initializes to 5

Per gli array puoi usare qualcosa come memset. Per Windows utilizzare ZeroMemory o SecureZeroMemory.

Modifica: Si prega di consultare il post di @ litb, mostra come è possibile inizializzare a 0 per gli array che utilizzano l'inizializzazione non diretta come sopra.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top