Template soll Makro ersetzen
-
Ist das so korrekt? In Templates bin ich noch nicht sonderlich fit.
template<typename T> inline void safeDelete(T pointer) { if (pointer == NULL) return; delete pointer; pointer = NULL; }
-
if (pointer == NULL) return;
unnütz.
-
Optimizer schrieb:
Ist das so korrekt?
Der Test auf NULL ist völlig sinnlos, da er bereits von delete durchgeführt wird.
-
der code ist doch sowieso unnütz, da delete auf einen Nullpointer erlaubt ist.
-
Stimmt.
-
Optimizer schrieb:
Ist das so korrekt? In Templates bin ich noch nicht sonderlich fit.
template<typename T> inline void safeDelete(T pointer) { if (pointer == NULL) return; delete pointer; pointer = NULL; }
ja, ist korret.
aber
pointer = NULL;
ist komisch, denn von außen sieht man sie änderung nicht.
ich nehme an, du meintest
inline void safeDelete(T& pointer)
damit sieht man auch von außen die änderung.
int* a=new int;
safeDelete(a);//und a wird auch auf NULL gesetzt.dann kommt noch, daß man in c++ heutzutage 0 statt NULL schreibt.
und zuguterletzt ist das if in der tat ein wenig unnütz, weil irgendwelche spaßvögel definiert haben, daß delete(0) ohne absturz klappt und ganz ok ist. es tut halt nix.
also
template<typename T> inline void safeDelete(T& pointer) { delete pointer; pointer = 0; }
ok, mit diesem code kann man sogar ein paar monate lang fröhlich sein. nach dem durcharbeen des buchs "effektiv c++ programmieren" wirste aber langsam auf den dreh kommen, daß man keinen code baut, der davon lebt, daß man lauter fehler wie doppelte deletes durch safeDelete halbwegs kittet, sondern daß man einfach keine doppelten deletes mehr macht.
new steckt in nem konstruktor, delete in nem destruktor. fast immer. da gibts schonmal keinen bedarf. ansonsten steckt new am funktionsanfang und delete am ende (oh, mist, nicht exceptionsicher, das hau ich schnell in ein konstruktor/destruktor-paar). und manchmal in zueinanderpassenden methoden wie push/pop.
-
volkard schrieb:
dann kommt noch, daß man in c++ heutzutage 0 statt NULL schreibt.
Ich habe mir immer gedacht, dass man wenn schon, immer 0L schreiben soll.
Oder wie in 'Effekiv C++ programmieren' ne NullPtr-Klasse schreiben.
-
*lol* auf das T& hätt ich auch kommen können.
Das kommt davon, wenn man einfach das Makro kopiert.Vielleicht ist auch der Name safeDelete ein wenig irreführend. Die Funktion ist nicht dafür da, um die Sicherheit zu erhöhen, sondern um den Pointer beim löschen noch auf NULL zu setzen, was seltsamerweise jetzt nicht geklappt hat (
).
Doppelte deletes mach ich nicht, ich hab einfach ein Array von Zeigern und kein Bock, immer delete und nochmal = NULL zu sagen. In ein Konstruktor gehört das in dem Fall nicht rein, weil das Array ein statisches Datenelement ist.
btw. const int NULL = 0;
-
Optimizer schrieb:
Vielleicht ist auch der Name safeDelete ein wenig irreführend.
das ist aber der übliche name.
Die Funktion ist nicht dafür da, um die Sicherheit zu erhöhen, sondern um den Pointer beim löschen noch auf NULL zu setzen, was seltsamerweise jetzt nicht geklappt hat (
).
Doppelte deletes mach ich nicht, ich hab einfach ein Array von Zeigern und kein Bock, immer delete und nochmal = NULL zu sagen. In ein Konstruktor gehört das in dem Fall nicht rein, weil das Array ein statisches Datenelement ist.
btw. const int NULL = 0;
hab die argumene nicht nachvollziehen können. ich widerspreche einfach mal.
-
daß man keinen code baut, der davon lebt, daß man lauter fehler wie doppelte deletes durch safeDelete halbwegs kittet, sondern daß man einfach keine doppelten deletes mehr macht.
Wie gesagt, ich mach keine doppelten deletes, ganz sicher nicht. Dass der Zeiger auf NULL gesetzt wird, brauch ich aus anderen Gründen.
new steckt in nem konstruktor, delete in nem destruktor. fast immer.
Ja, aber nicht bei einem statischem Array von Zeigern.
dann kommt noch, daß man in c++ heutzutage 0 statt NULL schreibt.
Gegen mein const int spricht doch deshalb trotzdem nichts, ich finde NULL besser lesbar.
-
Optimizer schrieb:
Wie gesagt, ich mach keine doppelten deletes, ganz sicher nicht. Dass der Zeiger auf NULL gesetzt wird, brauch ich aus anderen Gründen.
hab ich schon verstanden, daß es nicht an doppelten deletes hängt. da ich die anderen gründe nicht kenne, hab ich die anderen gründe aber nicht verstanden. kommt ja mal vor.
Gegen mein const int spricht doch deshalb trotzdem nichts, ich finde NULL besser lesbar.
gegen const int spricht gar nix.
hat Scott echt ne NullPtr-Klasse gebaut? muß wohl mal die neue ausgabe lesen. wozu machte er das? und wozu 0L?gegen NULL und für 0 sprechen zwei gewichtige gründe:
a) die meisten schreiben 0, daher gewöhne dich auch dran, du wirst viel fremden code lesen und andere werden ab und zu auch deinen code lesen. haste dich erstmal an 0 gewöhnt, isses gar nicht so schlimm. der gute programmierstil ist auch ne kulturelle erscheinung und nicht allein auf technischen argumenen aufsetzend. so wie der gute stil beim essen auch zum teil völlig willkürlich und gegen jeden effizienzgedanken ist. (ja, das macht mich auch traurig.)
b) wer 0 schreibt, ist "in" und wird eher ernst genommen.edit:
falls safeDelete nen ganz falschen Namen hat und eher sowas wie removeObjectFromGlobalHashtable sein sollte, könnte ich eventuell geneigt sein, anzunehmen, daß es möglicherweise kein gravierender fehler ist.
-
volkard schrieb:
hat Scott echt ne NullPtr-Klasse gebaut? muß wohl mal die neue ausgabe lesen. wozu machte er das?
Um Mehrdeutigkeiten wie die folgende aufzulösen:
int foo(int); int foo(char*); int bar() { return foo(NULL); }
-
da ich die anderen gründe nicht kenne, hab ich die anderen gründe aber nicht verstanden. kommt ja mal vor.
lol
Naja weil ich durch mein array durchlauf und alle Objekte berechne, wo kein Nullzeiger ist. Wenn ich n Objekt lösche, soll der Zeiger darauf deshalb natürlich NULL sein. Damit ich das nicht vergesse und mir außerdem überall eine Zeile Code spare, hab ich die Funktion geschrieben. Gefällt mir zumindest besser als ein Makro.0L? Wüsste ich auch gern. Ein long hat doch immer mindestens 32 Bit, das würde auf einem 16Bit-System bestimmt zu Problemen (oder wenigstens einem Typecast) führen IMO.
-
Es wurde foch auch schon ein nullptr als Schlüsselwort für einen kommendne C++ Standard vorgschlagen.
-
Ein long hat doch immer mindestens 32 Bit
falsch!?
-
Um Mehrdeutigkeiten wie die folgende aufzulösen:
int foo(int); int foo(char*); int bar() { return foo(NULL); }
Ist ja auch keine Hexerei:
class{ public: template<class T> operator T*(){return 0;} }p0,NULL; class{ public: operator int(){return 0;} }n0; void say(int){cout<<"int"<<endl;} void say(void*){cout<<"ptr"<<endl;} int main() { say(p0); say(n0); return 0; }
Und mein Compiler kriegt das ohne Runtime overheat hin.
-
Dein NULL verhält sich nicht wie ein allgemeiner Null-Zeiger.
Du hast Zeiger auf Klassenelemente vergessen, also z.B. void (foo::)() oder int foo::.
-
Ausserdem musst du operator& überladen. NULL hat keine Adresse.