2

サブクラスで演算子 new/delete をオーバーロードしていますが、かなり奇妙に思える動作に気付きました。以下のサンプルコードを見てください。

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

class Base
{
public:

    virtual ~Base()
    {
    }
};

class Derived : public Base
{
public: 

    void* operator new(unsigned int size, int capacity)
    {
        printf("> new(unsigned int, int)\n");
        return malloc(sizeof(Derived));
    }

    void operator delete(void* ptr, int)
    {
        printf("> delete(void*, int)\n");
        free(ptr);
    }

    void operator delete(void* ptr)
    {
        printf("> delete(void*)\n");
        free(ptr);
    }
};

int main(int argc, char** argv)
{
    Base* base = new (0) Derived();
    delete base;

    return 0;
}

このコードは、Visual Studio 2010 でコンパイルすると、次の出力を生成します。

> new(unsigned int, int)
> delete(void*)

一致する削除演算子 ( Derived::operator delete(void*, int)) がここで呼び出されないのはなぜですか? 何をしても、一致する演算子 delete を呼び出すコードを取得できません。

4

1 に答える 1

5

基本的なマントラ:

配置削除式はありません。

placement-new を使用してオブジェクトを作成する場合は、手動で破棄してから解放関数を呼び出す必要があります。

Base * p = new (0) Derived;

p->~Derived();

Derived::operator delete(p, 0);

標準の new 式の結果としてdelete base;取得したことがないため、コードで言うのは一種の未定義の動作です。baseまったく異なることを行う配置の新しい割り当て関数を定義した可能性が十分にあり、標準のoperator delete-deallocation 関数を呼び出すと、完全な混乱が生じる可能性があります。あなたのプログラムでそれがうまくいくのはたまたまです。

于 2013-05-16T19:29:06.270 に答える