9

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

我怎么能在我的重载new运算符中失败并且仍然不调用我的构造函数?本质上我想实现类似new (std::nothrow).

这是一个例子来说明我的意思。请注意,我正在测试的系统没有内存保护。所以访问NULL不会做任何事情

示例 1:重载 new 运算符

#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

显然,在failed时调用了 constrcutornew

示例 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    

显然,failed时没有调用constrcutornew

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

4

1 回答 1

9

Whether the compiler checks for a null pointer after calling operator new or not, before calling the destructor, depends on whether the allocator function has a non-throwing exception specification or not. If not, the compiler assumes that operator new will throw if no memory is available. Otherwise, it assumes that operator new will return a null pointer. In your case, your operator new should be:

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

or if you can count on C++11 support:

void* operator new( size_t size, unsigned int extra) noexcept
{
}
于 2013-03-08T10:43:50.393 回答