运算符new []不接收额外的字节

时间:2012-12-06 15:08:10

标签: c++ operator-overloading new-operator destructor

我有这样的代码

#include <cstdlib>

class Foo
{
    int m_data;

public :    
    Foo() : m_data(0) { }

    /*~Foo()
    {
    }*/

    static void* operator new[](const size_t size)
    {
        return malloc(size);
    }

    static void operator delete[](void* data)
    {
        free(data); 
    }
};

int main()
{
    Foo* objects = new Foo[5];

    delete [] objects;
}

在这种情况下,我在运算符新重载中接收size的值为20个字节(sizeof(int) * 5)。但是如果我取消注释析构函数,我得到size为24个字节。是的,我现在用这些额外的字节来存储已分配内存的大小并等于sizeof(size_t)。我无法理解为什么只有在我明确地实现析构函数时才能得到它们。如果我不这样做,编译器应该做同样的事情或者我错过了什么?

我在MSVS 2010和2012上尝试过这种方法。编译为Win32。

2 个答案:

答案 0 :(得分:7)

来自new[]的{​​{1}}请求的“额外字节”不会用于“存储已分配内存的大小”,正如您似乎相信的那样。它们用于在数组中存储个元素,以便operator new[]知道要调用多少个析构函数。在你的例子中,析构函数是微不足道的。没有必要打电话给他们。因此,不需要分配这些额外的字节并存储元素数。

“已分配内存的大小”(即块的大小,以字节为单位)是一个完全不同的故事。它由较低级别的分配器独立存储和检索 - 在您的示例中为delete[]

换句话说,在一般情况下,由malloc/free分配的内存块在实际数据前面有两组额外字节:块大小(以字节为单位)(由new[]引入)和元素count(由malloc引入)。第二个是可选的,正如您的示例所示。第一个通常始终存在,因为它由new[]无条件地分配。即即使您只请求malloc,您的malloc来电也会实际分配超过20个字节。 20将使用这些额外字节来以字节为单位存储块大小。

后者也会出现在你的例子中。你只是看不到它,因为它发生在malloc内。

答案 1 :(得分:6)

如果编译器不需要调用析构函数,则不需要记住要调用多少个析构函数。如果你有一个需要破坏的数据成员,比如std::string,你就不会发现这种行为,因为编译器总是需要破坏它。