У меня есть программа на C++, где оператор new
перегружен. Проблема в том, что , если мое распределение в операторе new
терпит неудачу, я все равно вызываю конструктор. Я знаю, что могу избежать этого, бросив std::bad_alloc
, но я не хочу этого делать.Как реализовано `new (std :: nothrow)`?
Как я могу сбой в моем перегруженном операторе new
и до сих пор не вызывать мой конструктор? По сути, я хочу реализовать что-то вроде new (std::nothrow)
.
Вот пример, чтобы проиллюстрировать, что я имею в виду. Обратите внимание, что система, которую я тестирую , не имеет защиты памяти. Таким образом, доступ к NULL
не делает ничего
Пример 1: перегруженные новый оператор
#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;
}
выводе для этого:
$ ./a.out
Test constructor
this: 00000000
t: 00000000
Очевидно, что constrcutor становится вызывается, когда new
не удалось.
Пример 2: декларация Огромный класса с новым (станд :: 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;
}
выводом для этого:
this: 00000000
t: 00000000
Очевидно, что constrcutor является не вызывалась когда new
не удалось.
Как я могу реализовать new (std::nothrow)
вид функциональности в моем перегружен new
оператор?
Спасибо большое, я никогда бы не догадался ответ. Вопрос, независимо от того, что вы сказали, документирован ли он где-либо в стандарте C++ 2003? – tinkerbeast
§5.3.4/13: «Если функция распределения возвращает значение null, то инициализация не должна выполняться, функция деаллокации не должна вызываться, а значение нового выражения должно быть null». –
На самом деле, как в C++ 11, так и в C++ 03, поведение задается в '[basic.stc.dynamic.allocation]/3'.Для C++ 11 формулировка такова: «Если функция распределения, объявленная с не-бросающей спецификацией исключений, не может выделить хранилище, она должна вернуть нулевой указатель. Любая другая функция распределения, которая не может распределить память, должна указывать на ошибку только выбрасывая исключение типа, который будет соответствовать обработчику типа std :: bad_alloc. " Текст C++ 03 очень похож. – Mankarse