memset() o inizializzazione del valore per azzerare una struttura?

memset() o inizializzazione del valore per azzerare una struttura?

Questi due costrutti sono un molto diversi nel loro significato. Il primo usa un memset funzione, che ha lo scopo di impostare un buffer di memoria su un determinato valore . Il secondo per inizializzare un oggetto . Lascia che te lo spieghi con un po' di codice:

Si supponga di avere una struttura con membri solo di tipi POD ("Dati vecchi semplici" - vedi Cosa sono i tipi POD in C++?)

struct POD_OnlyStruct
{
    int a;
    char b;
};

POD_OnlyStruct t = {};  // OK

POD_OnlyStruct t;
memset(&t, 0, sizeof t);  // OK as well

In questo caso scrivendo un POD_OnlyStruct t = {} o POD_OnlyStruct t; memset(&t, 0, sizeof t) non fa molta differenza, poiché l'unica differenza che abbiamo qui è l'allineamento byte impostati su valore zero in caso di memset Usato. Dal momento che normalmente non hai accesso a quei byte, non c'è differenza per te.

D'altra parte, dato che hai contrassegnato la tua domanda come C++, proviamo un altro esempio, con tipi di membri diversi da POD :

struct TestStruct
{
    int a;
    std::string b;
};

TestStruct t = {};  // OK

{
    TestStruct t1;
    memset(&t1, 0, sizeof t1);  // ruins member 'b' of our struct
}  // Application crashes here

In questo caso usando un'espressione come TestStruct t = {} è buono e usando un memset su di esso porterà al crash. Ecco cosa succede se usi memset - un oggetto di tipo TestStruct viene creato, creando così un oggetto di tipo std::string , poiché è un membro della nostra struttura. Successivamente, memset imposta la memoria in cui si trova l'oggetto b era localizzato a un certo valore, diciamo zero. Ora, una volta che il nostro oggetto TestStruct esce dall'ambito, verrà distrutto e quando arriverà il turno del suo membro std::string b vedrai un arresto anomalo, poiché tutte le strutture interne di quell'oggetto sono state rovinate dal memset .

Quindi, la realtà è che quelle cose sono molto diverse e anche se a volte è necessario memset un'intera struttura a zero in certi casi, è sempre importante assicurarsi di capire cosa si sta facendo e non commettere errori come nel nostro secondo esempio.

Il mio voto:usa memset sugli oggetti solo se è richiesto, e usa il predefinito inizializzazione x = {} in tutti gli altri casi.


A seconda dei membri della struttura, le due varianti non sono necessariamente equivalenti. memset imposterà la struttura su tutti i bit zero mentre l'inizializzazione del valore inizializzerà tutti i membri sul valore zero. Lo standard C garantisce che siano gli stessi solo per i tipi integrali, non per i valori a virgola mobile o i puntatori.

Inoltre, alcune API richiedono che la struttura sia effettivamente impostata su tutti i bit zero. Ad esempio, l'API del socket Berkeley utilizza le strutture in modo polimorfico, e lì è importante impostare davvero l'intera struttura a zero, non solo i valori che sono evidenti. La documentazione dell'API dovrebbe indicare se la struttura deve davvero essere tutti bit zero, ma potrebbe essere carente.

Ma se nessuno di questi, o un caso simile, si applica, dipende da te. Quando si definisce la struttura, preferirei l'inizializzazione del valore, poiché comunica l'intento in modo più chiaro. Ovviamente, se devi azzerare una struttura esistente, memset è l'unica scelta (beh, a parte inizializzare ogni membro a zero a mano, ma che normalmente non sarebbe fatto, specialmente per strutture di grandi dimensioni).


Se la tua struttura contiene cose come :

int a;
char b;
int c;

Quindi verranno inseriti dei byte di riempimento tra "b" e "c". memset() li azzererà, l'altro modo no, quindi ci saranno 3 byte di spazzatura (se i tuoi int sono 32 bit). Se intendi usare la tua struct per leggere/scrivere da un file, questo potrebbe essere importante.