【问题标题】:Operator new[] does not receive extra bytes运算符 new[] 不接收额外字节
【发布时间】:2012-11-24 15:40:45
【问题描述】:

我有这样的代码

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

在这种情况下,我在 operator new 重载中收到 size 的值作为我想要的 20 个字节 (sizeof(int) * 5)。但是,如果我取消注释析构函数,我会得到 size 为 24 个字节。是的,我现在这些额外的字节用于存储分配内存的大小,等于sizeof(size_t)。我不明白为什么只有当我明确地实现析构函数时才能得到它们。如果我不这样做,编译器应该做完全相同的事情还是我错过了什么?

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

【问题讨论】:

  • 为什么你认为编译器“应该做同样的事情”?
  • 我认为如果我根本不实现析构函数,编译器会为我生成它,它看起来就像我在上面的示例中评论过的那样 - 为空。
  • 从概念上讲,情况就是这样。但是,当编译器隐式实现一个完全不做任何事情的析构函数时,这种析构函数称为trivial。这样的析构函数实际上并没有起到任何作用,编译器也不必调用它。实际上,即使你显式实现了一个空的析构函数,编译器也不必调用它,但你的编译器显然想保留调用。
  • 感谢您的回答。我真的不知道

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


【解决方案1】:

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

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

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

后者也发生在您的示例中。你根本看不到它,因为它发生在 malloc 内部。

【讨论】:

    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2021-02-16
      • 1970-01-01
      • 2012-07-31
      • 1970-01-01
      • 2017-11-28
      • 1970-01-01
      • 2011-05-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多