首页 > 解决方案 > 重载运算符 new[] 的行为取决于析构函数

问题描述

以下代码片段重载operator new[]并打印出size所需的指针地址

class MyClass
{
private:
    int _data;    //sizeof(MyClass) == 4

public:
    void* operator new[](size_t size)
    {
        cout << "MyClass::operator new[]" << endl;
        cout << "size = " << size << endl;
        void* p = malloc(size);
        cout << "p = " << p << endl;
        return p;
    }
};

int main()
{
    MyClass* a = new MyClass[100];
    cout << "a = " << a << endl;
}

输出

>>  MyClass::operator new[]
>>  size = 400
>>  p = 0x55e335a3f280
>>  a = 0x55e335a3f280

但是,通过显式添加/定义析构函数

class MyClass
{
...
public:
    ...
    ~MyClass() {}
};

int main()
{
    MyClass* a = new MyClass[100];
    cout << "a = " << a << endl;
}

结果改变了

>>  MyClass::operator new[]
>>  size = 408
>>  p = 0x564f30cd7280
>>  a = 0x564f30cd7288

表示表达式new[]正在从 . 请求额外的 8 字节内存operator new[]。额外的内存字节似乎是存储数组的大小,甚至可以访问!

cout << "info: " << *(reinterpret_cast<size_t*>(a) - 1) << endl;

结果

>>  info: 100

我的问题是谁以及为什么使用这 8 个字节的信息?这是标准的一部分吗?如果是这样,是否有解释为什么它被设计成这样?

标签: c++memorynew-operator

解决方案


指定调用任何数组时是否存在以及有多少开销new。这种行为完全在编译器的宽容范围之内。额外的空间通常用于指示数组中有多少元素。

在调用delete[]时,需要调用每个元素的析构函数;这只有在我们知道有多少元素的情况下才能做到。在元素具有微不足道的析构函数的情况下,不需要调用它们,因此不需要空间。

请注意,尽管实现通常委托给std::freein operator delete,但不能保证,您也应该重载operator delete


推荐阅读