为什么new []分配额外的内存?

时间:2009-11-13 09:32:44

标签: c++

我正在阅读“用C ++思考”,我对新运算符感到困惑。以下是本书的代码:

//: C13:ArrayOperatorNew.cpp
// Operator new for arrays

#include <new> // Size_t definition
#include <fstream>

using namespace std;

ofstream trace("ArrayOperatorNew.out");

class Widget 
{
    enum { sz = 10 };
    int i[sz];

  public:

    Widget() { trace << "*"; }
    ~Widget() { trace << "~"; }

    void* operator new(size_t sz) 
    {
        trace << "Widget::new: "
              << sz << " bytes" << endl;
        return ::new char[sz];
    }

    void operator delete(void* p) 
    {
        trace << "Widget::delete" << endl;
        ::delete []p;
    }

    void* operator new[](size_t sz) 
    {
        trace << "Widget::new[]: "
              << sz << " bytes" << endl;
        return ::new char[sz];
    }

    void operator delete[](void* p) 
    {
        trace << "Widget::delete[]" << endl;
        ::delete []p;
    }
};

int main() 
{
    trace << "new Widget" << endl;
    Widget* w = new Widget;
    trace << "\ndelete Widget" << endl;
    delete w;
    trace << "\nnew Widget[25]" << endl;
    Widget* wa = new Widget[25];
    trace << "\ndelete []Widget" << endl;
    delete []wa;
} ///:~

,这是“ArrayOperatorNew.out”

中跟踪的内容
new Widget
Widget::new: 40 bytes
*
delete Widget
~Widget::delete
new Widget[25]
Widget::new[]: 1004 bytes
*************************
delete []Widget
~~~~~~~~~~~~~~~~~~~~~~~~~
Widget::delete[]

我对数字1004感到困惑。为什么它不是1000?这本书说:

  

这个额外的四个字节是 的地方   系统会保留有关的信息   数组,特别是数量   数组中的对象。

但是系统是什么?这是如何完成的?编译器有帮助吗?

5 个答案:

答案 0 :(得分:5)

当使用new []时,运行时需要一些方法来记住分配的数组的大小,因此它知道在使用delete []时要释放多少。在你的特定实现中,它的记忆方式是分配保存大小的额外四个字节(它不必以这种方式工作)。

您可以在C++ FAQ

中详细了解相关信息

答案 1 :(得分:2)

答案 2 :(得分:1)

这是一个依赖于编译器的细节。

当调用delete []时,它只传递一个参数 - 指向数组的指针。为了正确运行,它必须知道在恰当数量的对象上执行析构函数的元素数量。所以它必须在某个地方获取这些信息。

典型的方法是new []在数组有效负载之前加上一个额外的size_t来存储元素的数量。因此,分配的空间量将是

sizeof( size_t ) + numberOfElements * sizeof ( ObjectType )

答案 3 :(得分:0)

当使用new分配数组时,在分配的块的开头使用另一个字来保持分配的字节数。
由于C ++数组不保留有关其大小的信息,因此内存管理器必须保留已分配内存大小的标签,当使用delete []时,读取已分配的Byes的数量,然后内存管理器收取该内存量。 这就是为单个变量调用delete []可能是灾难性的原因 并且为数组调用delete会导致内存泄漏。

答案 4 :(得分:0)

内存管理必须保留一些有关内存块大小的信息。如果没有该信息,删除/删除[]将无法正常工作(如果删除,则可能不需要此信息,因为编译器知道要删除的对象的大小)。

如何保存信息以及new / delete的实现细节在哪里。它可能会根据您使用的编译器或内存管理库(例如SmartHeap)而改变。

有时会分配额外的内存来检测编程错误(比如写入已分配内存的边界)。