Array of structs og nye / slette

stemmer
7

Jeg har en struct som dette:

class Items 
{
private:
    struct item
    {
        unsigned int a, b, c;
    };
    item* items[MAX_ITEMS];
}

Si Jeg ønsket å 'slette' en vare, som så:

items[5] = NULL;

Og jeg laget et nytt element på samme sted senere:

items[5] = new item;

Ville jeg fortsatt trenger å ringe delete[]for å rydde opp dette? Eller vil ikke dette være nødvendig ettersom grensene for matrise items[]er kjent før kompilering?

Setter som peker til NULL gyldig eller skal jeg kalle slette det?

Publisert på 12/01/2009 klokken 00:53
kilden bruker
På andre språk...                            


8 svar

stemmer
15

Du må ringe deletefør den settes til NULL. (Innstilling den til NULL er ikke nødvendig, det bare bidrar til å redusere feil hvis du ved et uhell prøver å dereference pekeren etter å ha slettet den.)

Husk at hver gang du bruker new, må du bruke deletesenere på samme pekeren. Bruk aldri en uten den andre.

Også new []og delete []gå sammen på samme måte, men du må aldri blande new []med deleteeller newmed delete []. I ditt eksempel, siden du opprettet objektet med new(i stedet for new []noe som ville skape en rekke objekter) må du slette objektet med delete(i stedet delete []).

Svarte 12/01/2009 kl. 01:04
kilden bruker

stemmer
6

Som Kluge påpekt, vil du lekker objektet på indeksen 5 sånn. Men dette egentlig høres ut som du ikke bør gjøre dette manuelt, men bruke en beholder klasse inne Item. Hvis du ikke egentlig trenger å lagre disse itemobjektene som pekere, bruke std::vector<item>i stedet for det utvalg av MAX_ITEMSpekere. Du kan alltid sette inn eller slette vektorelementer i midten i tillegg hvis du må.

I tilfelle du trenger å oppbevare gjenstander som pekere (vanligvis hvis struct itemer faktisk polymorfe, i motsetning til i ditt eksempel), kan du bruke boost :: ptr_vector <item> fra Boost.PtrContainer stedet.

Eksempel:

class Items {
private:
    struct item {
        unsigned int a, b, c;
    };
    std::vector<item> items;
}

if (items.size() > 5) // (just to ensure there is an element at that position)
    items.erase(items.begin() + 5); // no need to use operator delete at all
Svarte 12/01/2009 kl. 01:13
kilden bruker

stemmer
1

Det er noen få, relaterte, spørsmål her:

  1. Ifølge koden du postet, er matrisen i seg selv ikke tildelt på haugen, med mindre structer, så du trenger ikke å delete[]matrisen. Hvis du opprettet array med new[]du ville ha til delete[]det.
  2. Koden postet ikke si hvordan objektene blir pekt på fra matrisen er tildelt. Hvis du fordele disse objektene på stakken du må ikke slette dem (igjen, dette er svært usannsynlig fordi pekere blir ugyldig når objektene de peker til å falle ut av omfang). Hvis du tildelt dem på haugen (med ny) så du slette dem når de faller ut av omfanget.
  3. Som andre allerede har foreslått, er livet mye enklere hvis du bruker en container - spesielt en STL container - og smarte tips - som for nå betyr pekere ut av Boost.
Svarte 12/01/2009 kl. 08:20
kilden bruker

stemmer
1

Bare for å være klart: du refererer til å kalle " delete[]". Jeg tror du mener delete.

Jeg nevner dette fordi C ++ har to separate operatører, operator deleteog operator delete[]. Den sistnevnte brukes til å slette rekker av gjenstander avsatt med operator new[], og trenger ikke gjelder i dette tilfelle. Du har en rekke pekere til objekter, som du må ha initialisert med gjentatte samtaler til operator newstedet for en enkelt samtale til operator new[].

Alt jeg egentlig prøver å si er: bruk av delete[]er forvirrende og tvetydig; endre det til delete.

Svarte 12/01/2009 kl. 08:07
kilden bruker

stemmer
1

Si Jeg ønsket å 'slette' en vare, som så:

elementer [5] = NULL;

Jeg vet lite Visual Basic, men det lukter som en Visual Basic programmering idiom, siden "Still a = None" (eller Null, jeg er ikke sikker på) ville slette objektet påpekt av en (eller snarere minske referanse teller, for COM objekter).


Som noen andre nevnt, bør du bruke enten:

delete items[5];
items[5] = newContent;

eller:

delete items[5];
items[5] = NULL;

Etter delete[5]den eneste mulig bruk av pekeren lagret i items[5]skaper problemer. Hva er verre er at det kan skje for å arbeide i begynnelsen, og begynne å mislykkes bare når du fordele noe annet over plassen tidligere brukt av *items[5]. De er årsakene som gjør C / C ++ programmering "interessant", dvs. veldig irriterende (selv for som liker C som meg).

Skrive bare delete items[5];sparer det kan være en ubrukelig skrive, men det er en prematur optimalisering.

Svarte 12/01/2009 kl. 01:50
kilden bruker

stemmer
1

Slik sletter du et element bruk:

slette elementer [5];

etter å ha slettet elementet er det lurt å sette slettet pekeren til NULL, så du vil ikke ha en feil hvis du senere slette den igjen ved en feiltakelse.

elementer [5] = NULL

Svarte 12/01/2009 kl. 01:14
kilden bruker

stemmer
0

Innstillingselementer [5] til NULL ikke slette minnet forbundet med elementet, det bare setter pekeren til elementet til NULL, derfor minnet er lekket.

Du kan slette elementet ved å ringe:

delete items[5];

Siden C ++ har ikke automatisk garbage collection, må du slette minnet som du ikke lenger trenger.

Svarte 12/01/2009 kl. 00:59
kilden bruker

stemmer
0

C ++ er ikke min sterke side, men jeg er ganske sikker på at du vil lekke minnet hvis du setter pekeren til NULL.

EDIT: Det blir lekket ville være minnet minnet blir pekt på av pekeren i rekken.

Svarte 12/01/2009 kl. 00:57
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more