如何实现`new(std :: nothrow)`?

时间:2013-03-08 10:34:58

标签: c++ memory-management new-operator

我有一个C ++程序,其中new运算符被重载。问题是 如果我在new运算符中的分配失败,我仍然在调用构造函数。 我知道我可以通过投掷std::bad_alloc来避免这种情况,但我不想这样做。

如何在我的重载new运算符中失败并仍然不调用我的构造函数? 基本上我想实现new (std::nothrow)

之类的东西

这是一个说明我的意思的例子。 请注意我正在测试的系统 on没有记忆保护。因此,访问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

显然,当new失败时,会调用 constrcutor。

示例2:使用new(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;
}

这个的输出是:

this: 00000000
t: 00000000    

new失败时, constrcutor显然 被调用。

那么如何在我的实现中实现new (std::nothrow)类功能 重载new运算符?

1 个答案:

答案 0 :(得分:9)

编译器在调用后是否检查空指针 在调用析构函数之前,是否operator new取决于 分配器函数是否具有非抛出异常 规格与否。如果没有,编译器会假设 如果没有可用内存,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
{
}