Ich habe ein C++ - Programm, in dem der Operator new
überlastet ist. Das Problem ist, dass , wenn meine Zuweisung in der new
-Operator fehlschlägt, ich immer noch den Konstruktor aufrufen. Ich weiß, dass ich das vermeiden kann, indem ich std::bad_alloc
werfe, aber ich will das nicht tun.Wie wird `new (std :: nothrow)` implementiert?
Wie kann ich in meinem überladenen new
-Operator fehlschlagen und meinen Konstruktor immer noch nicht aufrufen? Im Wesentlichen möchte ich etwas wie new (std::nothrow)
implementieren.
Hier ist ein Beispiel zur Veranschaulichung, was ich meine. Beachten Sie, dass das getestete System keinen Speicherschutz hat. So NULL
Zugriff tut nichts
Beispiel 1: Überladene neue Betreiber
#include <stdio.h>
#include <stdlib.h>
#include <memory>
class Test {
public:
Test(void) {
printf("Test constructor\n");
}
void print(void) {
printf("this: %p\n", this);
}
void* operator new(size_t size, unsigned int extra) {
void* ptr = malloc(size + extra);
ptr = NULL; // For testing purposes
if (ptr == NULL) {
// ?
}
return ptr;
}
};
int main(void) {
Test* t = new (1) Test;
t->print();
printf("t: %p\n", t);
return 0;
}
Die ouput hierfür ist:
$ ./a.out
Test constructor
this: 00000000
t: 00000000
Klar, dass die constrcutor aufgerufen wird, wenn die new
fehlgeschlagen.
Beispiel 2: Sehr große Klassendeklaration mit neuer (std :: nothrow)
#include <stdio.h>
#include <stdlib.h>
#include <memory>
class Test {
int x0[0x0fffffff];
int x1[0x0fffffff];
int x2[0x0fffffff];
int x3[0x0fffffff];
int x4[0x0fffffff];
int x5[0x0fffffff];
int x6[0x0fffffff];
int x7[0x0fffffff];
int x8[0x0fffffff];
int x9[0x0fffffff];
int xa[0x0fffffff];
int xb[0x0fffffff];
int xc[0x0fffffff];
int xd[0x0fffffff];
int xe[0x0fffffff];
int xf[0x0fffffff];
public:
Test(void) {
printf("Test constructor\n");
}
void print(void) {
printf("this: %p\n", this);
}
};
int main(void) {
Test* t = new (std::nothrow) Test;
t->print();
printf("t: %p\n", t);
return 0;
}
Die ouput hierfür ist:
this: 00000000
t: 00000000
Klar, dass die constrcutor ist nicht genannt zu werden wenn die new
fehlgeschlagen.
Also wie implementiere ich new (std::nothrow)
Art der Funktionalität in meinem überladenen new
Operator?
Vielen Dank, hätte ich nie die Antwort erraten. Nur eine Frage, was immer du gesagt hast, ist es überall im C++ 2003 Standard dokumentiert? – tinkerbeast
§5.3.4/13: "Wenn die Zuweisungsfunktion null zurückgibt, darf die Initialisierung nicht erfolgen, die Freigabefunktion darf nicht aufgerufen werden, und der Wert des neuen Ausdrucks muss null sein." –
Tatsächlich wird das Verhalten in C++ 11 und C++ 03 in '[basic.stc.dynamic.allocation]/3' angegeben.Für C++ 11 lautet der Wortlaut wie folgt: "Wenn eine mit einer nicht auswerfenden Ausnahmebestimmung deklarierte Zuweisungsfunktion keinen Speicher zuweist, gibt sie einen Nullzeiger zurück. Jede andere Zuweisungsfunktion, die keinen Speicher zuweist, muss nur einen Fehler anzeigen eine Ausnahme eines Typs auslösen, der einem Handler vom Typ std :: bad_alloc entspricht. " Der Wortlaut von C++ 03 ist sehr ähnlich. – Mankarse