Как реализуется " new (std::nothrow)"?

у меня есть программа на C++, где new оператор перегружен. Проблема в том, что если мое распределение в new оператор не работает, я все еще вызываю конструктор. Я знаю, что могу избежать этого, бросая std::bad_alloc, но я не хочу этого делать.

как я могу потерпеть неудачу в моем перегруженном new оператор и все еще не вызываете Мой конструктор? По сути, я хочу реализовать что-то вроде new (std::nothrow).

вот пример, чтобы проиллюстрировать, что я имею в виду. Примечание. что система, которую я тестирую on не имеет защиты памяти. Так что доступ NULL ничего не происходит

Пример 1 : перегруженный оператор new

#include <stdio.h>
#include <stdlib.h>
#include <memory>

class Test {

public:

    Test(void) {
        printf("Test constructorn");
    }

    void print(void) {
        printf("this: %pn", 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: %pn", t);

    return 0;
}

выход для этого:

$ ./a.out
Test constructor
this: 00000000
t: 00000000

ясно constrcutor вызывается, когда new ошибка.

Пример 2: огромное объявление класса с новым (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 constructorn");
    }

    void print(void) {
        printf("this: %pn", this);
    }
};

int main(void) {

    Test* t = new (std::nothrow) Test;    
    t->print();
    printf("t: %pn", t);

    return 0;
}

выход для этого есть:

this: 00000000
t: 00000000    

ясно constrcutor составляет не вызывается, когда new ошибка.

Итак, как мне реализовать new (std::nothrow) функциональность в моем перегружен new оператор?

1 ответов


проверяет ли компилятор нулевой указатель после вызова operator new или нет, перед вызовом деструктора, зависит от имеет ли функция распределителя исключение non-throwing спецификация или нет. Если нет, компилятор предполагает, что operator new будет бросать, если нет памяти. Иначе, он предполагает, что operator new вернет нулевой указатель. В ваше дело, ваше operator new должно быть:

void* operator new( size_t size, unsigned int extra ) throw()
{
    //...
}

или если вы можете рассчитывать на поддержку C++11:

void* operator new( size_t size, unsigned int extra) noexcept
{
}