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

Operator new[] does not receive extra bytes

提问人:Pavel Dubsky 提问时间:12/6/2012 最后编辑:Pavel Dubsky 更新时间:5/15/2014 访问量:320

问:

我有这样的代码

#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;
}

在这种情况下,我根据需要将运算符 new 重载的值作为 20 个字节()。但是,如果我取消对析构函数的注释,我会得到 24 个字节。是的,我现在这些额外的字节用于存储分配的内存大小,并且等于 .我不明白为什么只有在我显式实现析构函数时才能获得它们。如果我不这样做,编译器应该做完全相同的事情,或者我错过了什么?sizesizeof(int) * 5sizesizeof(size_t)

我已经在 MSVS 2010 和 2012 上尝试过了。针对 Win32 编译。

C++ 运算符重载 new-operator 析构函数

评论

0赞 AnT stands with Russia 12/6/2012
为什么你认为编译器“应该做完全相同的事情”?
0赞 Pavel Dubsky 12/7/2012
我认为如果我根本不实现析构函数,编译器会为我制作它,它看起来像我在上面的示例中评论的那个 - 空。
1赞 AnT stands with Russia 12/7/2012
从概念上讲,情况就是这样。但是,当编译器隐式实现一个完全不执行任何操作的析构函数时,这种析构函数称为微不足道。这样的析构函数实际上并不起任何作用,编译器也不必调用它。实际上,即使你显式地实现了一个空的析构函数,编译器也不必调用它,但你的编译器显然希望保留调用。

答:

6赞 Puppy 12/6/2012 #1

如果编译器不需要调用析构函数,则不需要记住要调用多少个析构函数。如果您有一个需要解构的数据成员,则不会观察到这种行为,例如 ,因为编译器始终需要解构它。std::string

7赞 AnT stands with Russia 12/6/2012 #2

from 请求的“额外字节”不用于“存储分配的内存大小”,正如您似乎认为的那样。它们用于存储数组中元素的数量,以便知道要调用多少析构函数。在您的示例中,析构函数是微不足道的。没有必要打电话给他们。因此,无需分配这些额外的字节并存储元素计数。new[]operator new[]delete[]

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

换句话说,在一般情况下,由 分配的内存块在实际数据前面有两组额外的字节:以字节为单位的块大小(由 引入)和元素计数(由 引入)。第二个是可选的,如您的示例所示。第一个通常始终存在,因为它是由 无条件分配的。也就是说,即使您仅请求 .这些额外的字节将用于存储块大小(以字节为单位)。new[]mallocnew[]mallocmalloc2020malloc

后者也发生在你的例子中。你根本看不到它,因为它发生在里面.malloc