5

レガシーコードを見ていると、次のコードに似たものが見つかりました

void* legacy_type::operator new(size_t size) {
    return pool_alloc(size);
}

pool_alloc は、失敗した場合に決してスローせず、0 を返すことが知られています。

ここでは、 new の std::nothrow バリアントのオーバーロードはありません。

このコードが意味的に正しく、動作が明確に定義されているかどうかは疑問です。

new (std::nothrow) legacy_type;カスタムの pool_alloc を使用する必要がありますか? 私のコンパイラでは、まったくコンパイルされません。それは明確に定義された動作ですか?

this==0オーバーロードoperator newがゼロを返す場合、コンストラクターを実行してクラッシュさせる必要がありますか? 私のコンパイラでは実行されます(メンバーの初期化時にクラッシュします)。それは標準的な明確に定義された動作ですか?

4

1 に答える 1

2

1) いいえ、そうすべきではありません。これらは異なる機能です。また、操作の 1 つをオーバーロードすると、オーバーロードされていない場合、他のすべての操作は機能しませんoperator new。クラス スコープ内にあり、署名が受け入れられない場合、コンパイラは global を検索しないoperator newため、compile-error起こります。

new2) null ポインターを返す場合は、事後条件を破ります。n3376 18.6.1.1/3

必要な動作: 適切にアラインされたストレージ (3.7.4) への非 null ポインターを返すか、bad_-alloc 例外をスローします。この要件は、この機能の代替バージョンを拘束します。

0 を返したい場合は、次の署名を使用する必要があります

void* operator new(size_t) throw()

このオーバーロードを使用して 0 を返す場合、セグ フォールトはありません。

n3376 5.3.4/13

割り当て関数が null を返す場合、初期化は行われず、割り当て解除関数は呼び出されず、new-expression の値は null になります。

于 2013-10-31T12:51:30.163 に答える