C++ 为什么这些自定义的new和delete分配器的行为是这样的?

C++ 为什么这些自定义的new和delete分配器的行为是这样的?,c++,memory-management,new-operator,C++,Memory Management,New Operator,下面的代码有两个问题。一个是没有调用我的自定义运算符delete函数,特别是在数组版本中,而只是针对一个自定义类而不是int类型。另一个问题是我想了解为什么只为自定义类数组而不是内置类型数组分配了额外的8字节: #include <stdlib.h> #include <iostream> #include <exception> using namespace std; struct TestClass { uint32_t m; Tes

下面的代码有两个问题。一个是没有调用我的自定义运算符delete函数,特别是在数组版本中,而只是针对一个自定义类而不是int类型。另一个问题是我想了解为什么只为自定义类数组而不是内置类型数组分配了额外的8字节:

#include <stdlib.h>
#include <iostream>
#include <exception>
using namespace std;


struct TestClass
{
    uint32_t m;
    TestClass() {
        std::cout << "TestClass Constructor called\n";
    }
    ~TestClass()
    {
        std::cout << "TestClass Destructor called\n";
    }
};


size_t allocatedMemory = 0;

// Single version new
void* operator new(size_t count)
{
    void* mem = malloc(count);
    if (!mem) 
        throw bad_alloc();
    else
    {
        allocatedMemory += count;
        cout << "void operator new(size_t count) called with " << count << " size\n";

        return mem;
    }
}
// Array version new
void* operator new[](size_t count)
{
    void* mem = malloc(count);
    if (!mem)
        throw bad_alloc();
    else
    {
        allocatedMemory += count;
        cout << "void operator new[](size_t count) called with " << count << " size\n";

        return mem;
    }

}

// Single version delete
void operator delete(void* mem, size_t size)
{
    allocatedMemory -= size;
    free(mem);
    cout << "void operator delete(void* mem, size_t size) called with " << size << " size\n";
}
// Array version delete
void operator delete[](void* mem, size_t size)
{
    allocatedMemory -= size;
    free(mem);
    cout << "void operator delete[](void* mem, size_t size) called with " << size << " size\n";
}


int main()
{
    // WITH CUSTOM CLASS TYPE
    //=====================================
    cout << "Single TestClass:\n";
    TestClass* testObj = new TestClass; // operator new(size_t count) called with size of 4
    delete testObj; // operator delete(void* mem, size_t size) called with size of 4
    cout << "\n";

    cout << "TestClass array:\n";
    TestClass* testObjArray = new TestClass[5]; // operator new[](size_t count) called with size of 28
                                                // An extra 8 bytes
    delete[] testObjArray; // operator delete[](void* mem, size_t size) called with size of 28;
                            // An extra 8 bytes

    cout << "\n";

    // WITH BUILT-IN TYPE INT
    //=====================================
    cout << "Single uint32_t:\n";
    uint32_t* fourByteInt = new uint32_t; // operator new(size_t count) called with size of 4
                                        // Same as with single class TestClass object
    delete fourByteInt; // operator delete(void* mem, size_t size) called with size of 4
                        // Same as with single class TestClass object

    cout << "\n";

    cout << "uint32_t array:\n";
    uint32_t* fourByteIntArray = new uint32_t[5]; // operator new[](size_t count) called with size of 20
                                                // 8 bytes less than with the array of TestClass
    
    delete[]fourByteIntArray; // None of my operator functions called at all


}
#包括
#包括
#包括
使用名称空间std;
结构测试类
{
uint32_t m;
TestClass(){

std::cout您还需要定义

void operator delete(void* mem)

如果提供了用户定义的替换,则调用5-6)而不是(1-2), 除了未指定在调用时是调用(1-2)还是(5-6) 删除类型不完整的对象以及非类和 平凡可破坏的类类型


这里(1-2)是不带大小参数的delete版本,(5-6)是带大小参数的delete版本。因此,对于
uint32\t

的数组,未指定调用哪个版本的delete。对于第二个问题:
运算符new[]
使用为大小信息定义的实现开销(如您所怀疑的)以便删除可以知道需要调用多少析构函数,编译器理论上可以避免这种额外的开销;但这是一种实现定义的行为,我从来没有见过这种情况发生。通常,最好忽略/不重载
操作符new[]
正是出于这个原因。@Human Compiler我不明白。当你想删除一个int数组时,你只需将指向第一个int的指针传递给delete函数,它就得到一个指针。那么它怎么知道要删除多少元素或释放多少内存呢?@Zebrafish元数据通常在返回的分配块之前(特定于实现的详细信息)对于第一个问题,有一个重载
运算符delete[](void*)
,可以为普通类型调用,而不是
运算符delete(void*,size\t)
是您定义的。对于第二种情况,
delete
表达式的机制需要显式调用类的析构函数正确的次数,因此需要存储该值。同样,对于基本类型,实现不需要存储要释放的值的数量。@Zebrafish(具体实施)-delete从传递的指针中减去元数据头的大小。此调整后的指针现在指向元数据结构。因此,由于int是可破坏的,因此可以调用新函数的大小版本或没有“size”的版本?但我的int数组删除不调用size version,而是调用单个int删除是吗?这只是一个被调用的机会吗?在我的情况下,没有调用大小版本,如何释放大小,以便从'memoryAllocated'变量中减去它?@Zebrafish非类类型数组。单个int不是数组。至于获取大小,没有与平台无关的方法。
void operator delete[](void* mem)