2010-07-02 11 views
11

Ich wurde dies in einem kürzlichen Interview gefragt, im Grunde schrieb ich eine Funktion, um die Funktionalität von free und das Zuweisen von null zu kombinieren. Ich antwortete auf die folgende Weise:Eine Funktion schreiben, um einen Zeiger freizugeben und ihm zuzuweisen NULL

void main() 
{ 
     int *ptr; 
     ptr = new int; 
     ptr = newdelete(ptr); 
} 

(int*) newdelete (int *ptr) 
{ 
     delete(ptr); 
     return NULL; 
} 

So nach der Ausführung, die ptr lokal für main den Nullwert halten, wie ich es von der newdelete Funktion zurückzukehre. Wenn ich NULL in der newdelete Funktion gerade zugewiesen hatte, würde die ptr lokale zu newdelete nulliert werden und nicht die ptr lokale zu main.

Ich denke meine Lösung war korrekt, der Interviewer akzeptiert es auch. Er erwartete jedoch eine andere Antwort. Er bestand darauf, dass ich die nicht von der Funktion zurückgebe und immer noch das gewünschte Ergebnis erziele.

Gibt es eine Möglichkeit, das zu erreichen? Alles, was ich mir vorstellen kann, ist die Übergabe eines anderen Arguments, das den Zeiger auf den Zeiger ptr local zu main darstellt, aber ich sehe nicht, warum es besser ist als das, was ich getan habe!

+0

Ich denke, du meintest 'new int', weil' New' kein definierter 'C++' Operator ist. – ereOn

+1

Übergeben Sie einen Verweis auf den Zeiger. –

+0

http://stackoverflow.com/questions/1265666/reason-why-not-to-have-a-delete-macro-for-c/1265681#1265681 – Goz

Antwort

36

Gibt es eine Möglichkeit, das zu erreichen ??

template <typename T> void safeDelete(T*& p){ 
    delete p; 
    p = 0; 
} 

int main(int argc, char** arv){ 
    int * i = new int; 
    safeDelete(i); 
    return 0; 
} 
+0

+1, einfachste und flexible Lösung. – stinky472

+4

Da es nur Code gibt, ist der Grund, warum dies eine bessere Lösung ist, dass Sie garantieren, dass der Zeiger während des Aufrufs auf Null gesetzt wird. Mit dem Code in der Frage könnten Sie einfach den Rückgabewert überspringen (vergessen): '/ * p = */newdelete (p);' und der Speicher würde freigegeben, aber der Zeiger wäre nicht null. –

+6

Beachten Sie, dass Sie für Arrays eine zweite Version benötigen. –

8

Ich glaube, er hatte erwartet, so etwas wie:

void reset(int*& ptr) 
{ 
     delete(ptr); 
     ptr = NULL; 
} 

Eine noch sauberere Lösung wäre zu verwenden war ein boost::shared_ptr<> und einfach ptr.reset() zu nennen. Ich vermute jedoch, dass dies keine Option war.

+1

Was ist, wenn sie Shared Pointer-Semantik nicht wollen? Kein Punkt, der zusätzlichen Aufwand hat, wenn Sie ihn nicht brauchen. –

+1

@Peter scoped_ptr in diesem Fall, der ebenfalls Reset bereitstellt. – stinky472

+0

@Peter: Ich hätte 'scoped_ptr' anstelle von' shared_ptr' erwähnt (ich benutze letzteres öfter, so kam es mir zuerst in den Sinn). Unabhängig davon, ob es sich um einen freigegebenen Bereich oder einen Bereich handelt, ist die Verwendung eines intelligenten Zeigers sicherer als die Funktion 'safeDelete()' in Kombination mit unformatierten Zeigern. – ereOn

1

Wenn der requrement nicht eine Funktion schreiben ist, kann man immer einen Makro schreiben, dass es auch für Sie tun würde:

#define my_delete(x) { delete x; x = NULL; } 

Natürlich ist es wie dieser Aufruf wird Sie in alle Arten erhält von Problem:

my_delete(ptr++) 

Also, ich denke, ich bevorzuge den Nicht-Makro-Weg.

1

Sie nicht

Sie verwenden Smart-Pointer wie auto_ptr, shared_ptr, die sich nullt.