代码之家  ›  专栏  ›  技术社区  ›  Cedric H.

关于delete、delete[]、operator delete()等[duplicate]

c++
  •  3
  • Cedric H.  · 技术社区  · 16 年前

    可能的重复项:
    How does delete[] “know” the size of the operand array?
    ( POD )freeing memory : is delete[] equal to delete ?

    class A {};
    A* a = new A;
    //
    delete A;
    

    operator new() (全局的,或由a提供的专用的)分配适当数量的内存,然后调用a的构造函数 delete is调用,is将首先调用A的析构函数,然后调用 operator delete()

    正如我在TC++PL中读到的,这个“正确的内存量”是这样确定的:

    要取消分配new分配的空间,delete和delete[]必须能够确定分配的对象的大小。这意味着使用new的标准实现分配的对象将比静态对象占用稍多的空间。通常,一个词用来表示对象的大小。

    这是有道理的。但是这个词存储在哪里,以便用户访问 删除 删除 可以通过访问获取要删除的大小 a-sizeof<void*> ?

    我想这个问题的答案可以帮助我理解 delete [] 作品。我知道怎么做 new [] 删除[]

    但你怎么能 知道数组的大小吗?

    谢谢你的回答!

    1 回复  |  直到 9 年前
        1
  •  3
  •   Patrick    16 年前

    这完全取决于执行情况。

    大多数运行时确实会在返回内存之前存储内存大小( (BYTE *)p-sizeof(size_t) )但还有其他选择。在我自己的内存管理器中(是的,我写这种东西),在返回内存之前,我有一个更复杂的数据结构(使用指向链表的指针、校验和…)。实际上,由内存管理器决定在何处存储这些信息。

    除了分配的内存大小之外,new[]还将存储实例数,以便它知道要调用多少析构函数。这通常超出内存管理器的范围,通常由C++运行时/编译器本身处理。但是,实例的存储位置取决于编译器,尽管在实践中我希望它存储在返回内存之前(以及内存管理器存储的任何数据之后)。

    #include <iostream>
    
    typedef unsigned char Byte;
    
    class X
       {
       public:
          X() : m_value(1) {}
          ~X() {m_value = 0;}
       private:
          int m_value;
       };
    
    void print(Byte *p,int offset)
    {
    printf ("Value at %d: 0x%x (%d)\n", offset, p[offset], p[offset]);
    }
    
    void main()
    {
    X *x = new X[10];
    
    std::cout << "Address of x: " << x << std::endl;
    std::cout << "sizeof(X)   : " << sizeof(X) << std::endl;
    
    Byte *p = (Byte *)x;
    print(p,-1);
    print(p,-2);
    print(p,-3);
    print(p,-4);
    print(p,-5);
    print(p,-6);
    print(p,-7);
    print(p,-8);
    print(p,-9);
    print(p,-10);
    
    X *y = new X;
    std::cout << "Address of y: " << y << std::endl;
    
    p = (Byte *)y;
    print(p,-1);
    print(p,-2);
    print(p,-3);
    print(p,-4);
    print(p,-5);
    print(p,-6);
    print(p,-7);
    print(p,-8);
    print(p,-9);
    print(p,-10);
    }
    

    运行此命令将产生以下输出(在Visual Studio 2005上):

    Address of x: 00481DE4
    sizeof(X)   : 4
    Value at -1: 0x0 (0)
    Value at -2: 0x0 (0)
    Value at -3: 0x0 (0)
    Value at -4: 0xa (10)
    Value at -5: 0xc (12)
    Value at -6: 0x0 (0)
    Value at -7: 0x2f (47)
    Value at -8: 0x8 (8)
    Value at -9: 0x2f (47)
    Value at -10: 0x98 (152)
    Address of y: 00481E70
    Value at -1: 0xc (12)
    Value at -2: 0x0 (0)
    Value at -3: 0x2f (47)
    Value at -4: 0x8 (8)
    Value at -5: 0x2a (42)
    Value at -6: 0x98 (152)
    Value at -7: 0xf8 (248)
    Value at -8: 0xb0 (176)
    Value at -9: 0x0 (0)
    Value at -10: 0x48 (72)
    

    在第二种情况下,这些字节被省略,我们看到与第一种情况相同的模式(12,0,47,8)。我不知道VisualC++在哪里存储了分配的字节数,但是它证明了元素的数量确实存储在返回的指针之前(在VisualStudio 2005中)。