【问题标题】:How does delete[] keep track of the number of elements? [duplicate]delete[] 如何跟踪元素的数量? [复制]
【发布时间】:2012-05-11 19:47:15
【问题描述】:

可能重复:
How does delete[] “know” the size of the operand array?
How does the delete in C++ know how many memory locations to delete

我知道这是一个相当简单的问题,但我不确定这两行之间的区别(如果有的话):

double * a = new double[100];
delete[] a;
delete a;
free ((void*)a);

首先,所有这些调用(在没有其他调用的情况下使用每个调用)都会以相同的方式工作并释放 sizeof(double)*100 字节吗? 这让我想到了第二个问题,程序如何跟踪分配的内存大小?例如,如果我将我的 a 指针发送到一个函数,然后从我的函数中发送 delete[] 这个指针,我是否也会释放相同数量的内存?

谢谢

【问题讨论】:

    标签: c++ memory-management


    【解决方案1】:

    不同之处,过于简单化,是这样的:

    delete[] a;
    

    是正确的。所有其他都是不正确的,并且会表现出未定义的行为。

    现在,实际上,在我每天使用的所有编译器上,delete a; 每次都会做正确的事情。但你仍然不应该这样做。未定义的行为从不正确。

    free 调用也可能在现实世界中做正确的事情,但这只是因为你释放的东西没有非默认析构函数。例如,如果您尝试 free 某个带有析构函数的类,它肯定不会起作用——析构函数永远不会被调用。

    这是new/deletemalloc/free 之间最大的区别之一(不是唯一的区别)——前者调用构造函数和析构函数,而后者只是分配和释放空间。

    结合@Rob 在他现已删除的帖子中所说的话:

    简单的规则是这样的:每个 new[] 都需要一个 delete[]。 每一个新的都需要一个删除。 malloc 需要免费的。不 允许混搭。

    关于delete[]如何知道要删除多少个元素的问题,请看this response上一个重复的问题。

    【讨论】:

    • 但这并没有回答delete[]如何跟踪元素数量的问题。
    • @NathanFellman:是的,但我认为the linked duplicate 已经充分解决了这一问题。这里确实有两个问题——我回答了一个,而骗子回答了另一个。
    • 感谢您的回答。我担心的是为什么以下代码(来自stackoverflow.com/questions/10552656/…)在我销毁类时不会泄漏:class a { public: void * operator new(size_t l, int nb);双值; }; void *a::operator new (size_t l,int n) { return new char[l+ (n>1 ? n - 1 : 0)*sizeof(double)];如果我在“a”元素上调用 delete 时理解正确,则只有第一个字符会被删除,因为我没有调用 [] 版本
    • @lezebulon:链接帖子中的代码也表现出未定义的行为,因为该类没有提供operator delete 与它提供的operator new 一起使用。 (更多)
    • 话虽如此,我推测(这只是推测)内存不会泄漏,因为内存管理器通常是如何工作的。分配块通常按地址映射。因此,当您delete 指针时,即使您没有正确delete,也会在映射中查找正确的分配块。
    【解决方案2】:

    有人纠正我,如果我错了,但据我了解,当您之前使用newdelete[] 在使用new Type[] 之后分配内存时,您使用delete。当您使用malloc 分配内存时,将使用free

    请参阅 deletefree 上的 c++ 参考。

    【讨论】:

      【解决方案3】:

      关于双精度数组,所有形式的结果都是一样的——所有分配的内存都返回给系统。调用freedeletedelete[] 的区别在于:

      • free 只释放内存(为a 分配的内存大小由内存管理器在调用new 时存储)
      • delete在释放内存前调用已分配对象的析构函数
      • delete[]在释放内存之前调用数组中每个元素的析构函数

      如果分配对象的析构函数包含清除其他内存或系统资源(例如在对象生命周期内分配的文件或套接字描述符)的清理代码,则差异很重要。

      在 C++ 中,无论析构函数的内容如何,​​始终在单个实例上使用 delete,在对象/基元数组上使用 delete[] 是一个好习惯。

      【讨论】:

        猜你喜欢
        • 2016-12-03
        • 1970-01-01
        • 2015-10-29
        • 2019-10-09
        • 1970-01-01
        • 2021-11-22
        • 2014-11-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多