9

new演算子がオーバーロードされているC++プログラムがあります。問題は、オペレーターでの割り当てがnew失敗した場合でも、コンストラクターを呼び出していることです。投げることでこれを回避できることは知ってstd::bad_allocいますが、やりたくありません。

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

明らかに、失敗したときにコンストラクターが呼び出されていnewます。

例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ん。

では、オーバーロードされた演算子new (std::nothrow)にある種の機能を実装するにはどうすればよいですか?new

4

1 に答える 1

9

コンパイラが呼び出し後 operator new、デストラクタを呼び出す前にnullポインタをチェックするかどうかは、アロケータ関数に非スロー例外仕様があるかどうかによって異なります。operator newそうでない場合、コンパイラは、使用可能なメモリがない場合にスローすることを想定してい ます。operator newそれ以外の場合は、がnullポインタを返すと想定します。あなたの場合、あなたoperator newは次のようになります:

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

または、C ++ 11のサポートを期待できる場合:

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