代码之家  ›  专栏  ›  技术社区  ›  Martin Cote

为什么我们甚至需要“delete[]”操作符?

  •  30
  • Martin Cote  · 技术社区  · 17 年前

    delete 操作员(无支架)即使在 new[] 操作人员

    int* p = new int;
    

    应相当于分配一个由1个元素组成的数组:

    int* p = new int[1];
    

    如果这是真的,那么 删去 运算符可以总是删除数组,而我们不需要 delete[]

    有没有任何理由可以解释 删除[] C++中引入了操作符?我能想到的唯一原因是分配阵列占用的内存很小(必须将阵列大小存储在某个位置),因此 vs 删除[] 是一个小内存优化。

    7 回复  |  直到 5 年前
        1
  •  41
  •   Deduplicator    11 年前

    这样就可以调用单个元素的析构函数。是的,对于数组的POD,没有太大的区别,但是在C++中,可以有一些具有非平凡析构函数的对象数组。

    现在,你的问题是,为什么不 new delete 表现得像 new[] delete[] 摆脱 新[] 删除[] ? 我会回到Stroustrup的“设计和进化”书中,他说如果你不使用C++的特性,你就不必为它们付费(至少在运行时)。从现在的情况来看,一个 刚出现的 将尽可能高效地工作 malloc free . 如果 删去 这意味着,在运行时会有一些额外的开销(正如James Curran指出的)。

        2
  •  10
  •   NAND PolyThinker    5 年前

    delete[] 是因为很久以前我们 delete[cnt] delete[9] ,编译器只是忽略了 [] 但是编译没问题。当时,C++首先被前端处理,然后被馈送给普通的C编译器。他们不能把伯爵藏在窗帘下的某个地方,也许他们当时甚至想不起来。为了向后兼容,编译器很可能使用 [] 作为数组的计数,如果没有这样的值,那么他们从前缀中获得计数,因此它是双向工作的。后来,我们什么也没打 一切顺利。今天,我不认为 是必要的,但实现需要这样做。

    delete 删除单个对象。 删除[] 删除对象数组。对于 删除[] 为了工作,实现保持数组中元素的数量。我刚刚通过调试ASM代码再次检查了这一点。在我测试的实现(VS2005)中,计数被存储为对象数组的前缀。

    如果你使用 在单个对象上,count变量是垃圾,因此代码崩溃。如果你使用 删去 对于对象数组,由于某些不一致性,代码崩溃。我刚刚测试了这些案例!

    " 删去 只删除为数组分配的内存。”另一个答案中的语句不正确。如果对象是类, 删去 将调用DTOR。只需在DTOR代码中放置一个断点,然后 删去

    我想到的是,如果编译器&库假定 new 如果是对象数组,则可以调用 删去

        3
  •  8
  •   James Curran    17 年前

    由于其他人似乎都没有抓住你问题的重点,我只想补充一句,几年前我也有同样的想法,从来没有得到过答案。

    for(int i=0; i<1; ++i)

        4
  •  5
  •   Aaron    17 年前

    添加此选项,因为当前没有其他答案可以解决此问题:

    大堆 delete[] new[] delete 可以通过基类安全地删除,因此它可用于普通对象清理和多态清理:

    struct Base { virtual ~Base(); };
    struct Derived : Base { };
    int main(){
        Base* b = new Derived;
        delete b; // this is good
    
        Base* b = new Derived[2];
        delete[] b; // bad! undefined behavior
    }
    

    然而,在相反的情况下——非虚析构函数——标量 删去 应该尽可能便宜——它不应该检查对象的数量,也不应该检查要删除的对象的类型。这使得对内置类型或普通旧数据类型的删除非常便宜,因为编译器只需调用 ::operator delete

    int main(){
        int * p = new int;
        delete p; // cheap operation, no dynamic dispatch, no conditional branching
    }
    

    虽然不是对内存分配的彻底处理,但我希望这有助于澄清C++中可用的内存管理选项的广度。

        5
  •  4
  •   Fred Larson    17 年前
        6
  •  3
  •   Ates Goral    17 年前

    delete [] 确保在调用时调用每个成员的析构函数(如果适用于该类型) delete 只删除为数组分配的内存。

    http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=287

    而且,数组大小不存储在C++中的任何地方。 (感谢大家指出这一说法不准确。)

        7
  •  1
  •   NAND PolyThinker    5 年前

    delete[] 这是需要的。

    我用他的示例代码做了一些实验(在修正了一些拼写错误之后)。这是我的结果。 ~Base 需要一个职能机构 Base *b

    struct Base { virtual ~Base(){ }>; };
    struct Derived : Base { };
    int main(){
    Base* b = new Derived;
    delete b; // this is good
    
    <strike>Base</strike> b = new Derived[2];
    delete[] b; // bad! undefined behavior
    }
    

    编译和执行

    david@Godel:g++ -o atest atest.cpp 
    david@Godel: ./atest 
    david@Godel: # No error message
    

    修改程序 远离的

    struct Base { virtual ~Base(){}; };
    struct Derived : Base { };
    
    int main(){
        Base* b = new Derived;
        delete b; // this is good
    
        b = new Derived[2];
        delete b; // bad! undefined behavior
    }
    

    编译和执行

    david@Godel:g++ -o atest atest.cpp 
    david@Godel: ./atest 
    atest(30746) malloc: *** error for object 0x1099008c8: pointer being freed was n
    ot allocated
    *** set a breakpoint in malloc_error_break to debug
    Abort trap: 6
    

    delete[] b 在第一个例子中实际起作用;我只知道它不会给出编译器错误消息。