C ++:删除与免费和性能

时间:2008-11-30 13:06:00

标签: c++ pointers performance

  1. 考虑:

    char *p=NULL;
    free(p) // or
    delete p;
    

    如果我在free上使用deletep会怎样?

  2. 如果程序需要很长时间才能执行,比如10分钟,有没有办法将其运行时间缩短到5分钟?

7 个答案:

答案 0 :(得分:61)

有关new / delete和malloc / free的一些性能说明:

malloc和free 分别调用构造函数和解构函数。这意味着你的课程不会被自动化或自动取消初始化,这可能是不好的(例如未经执行的指针)!这对于像char和double这样的POD数据类型无关紧要,因为它们实际上没有ctor。

new并删除执行调用构造函数和解构函数。这意味着您的类实例会被初始化并自动取消初始化。但是,通常会出现性能损失(与普通分配相比),但这样做会更好。

我建议保持与new / malloc使用一致,除非你有理由(例如realloc)。这样,您可以减少依赖关系,减少代码大小和加载时间(但只能通过smidgin)。此外,你不会因为使用new分配的东西,或删除使用malloc分配的内容而陷入困境。 (这很可能会导致崩溃!)

答案 1 :(得分:13)

答案1:free(p)delete p都可以正常使用NULL指针。

答案2:没有看到代码的缓慢部分就无法回答。你应该分析代码!如果您使用的是Linux,我建议使用Callgrind(Valgrind的一部分)来查找执行的哪些部分花费最多的时间。

答案 2 :(得分:10)

问题一:什么都不会发生。

从目前的ISO / IEC 14882(或:C ++)草案:

  

20.8.15 C Library [c.malloc]

     

<cstdlib>的内容,即:free所在的内容,]与标准C库[(参见intro.refs)]标题<stdlib.h>相同,有以下变化:[没有任何影响这个答案]。

因此,来自ISO / IEC 9899:1999(或:C):

  

7.20.3.2 free函数

     

如果[{] ptr [参数]为空指针,则不会发生任何操作

再次从C ++标准中获取有关此delete的信息:

  

3.7.4.2解除分配函数[basic.stc.dynamic.deallocation]

     

提供给解除分配函数的第一个参数的值可以是空指针值;如果是,如果解除分配功能是标准库中提供的功能,呼叫无效

另见:

答案 3 :(得分:4)

如果使用NULL参数调用free,或使用NULL操作数删除,则不会发生任何事情。两者都被定义为接受NULL并且不执行任何操作。

您可以在C ++代码中更改任何可能影响其运行速度的内容。通常最有用的(按近似顺序)是:

  • 使用好的算法。这是一个很大的主题,但是,例如,我最近通过使用std :: vector而不是std :: list减少了一些代码的运行时间,在这种情况下,元素只在最后添加和删除
  • 避免重复长时间计算。
  • 避免不必要地创建和复制对象(但是每分钟发生不到1000万次的任何事情都不会产生任何显着差异,除非你正在处理非常大的,比如10的向量百万件)。
  • 编译优化。
  • 标记常用功能(再次,在10分钟运行时间内调用超过1亿次),如内联。

话虽如此,divideandconquer是绝对正确的 - 你不能有效地加速你的程序,除非你知道它花费的时间。有时,当你知道代码如何工作时,这可以被正确猜测,有时候这是非常令人惊讶的。所以最好分析一下。即使您无法对代码进行概要分析以确切了解时间花费的位置,如果您衡量了更改的效果,您通常也可以最终解决这些问题。

答案 4 :(得分:2)

关于问题2:
以前的答案非常好。但我只想补充一些关于预优化的内容。假设程序具有中等复杂性,通常适用90/10规则 - 即90%的执行时间花费在10%的代码中。 “优化”代码通常难以阅读和维护。所以,总是首先解决问题,然后看看瓶颈在哪里(分析是一个很好的工具)。

答案 5 :(得分:2)

正如其他人指出的那样,删除(或释放)NULL指针不会做任何事情。但是,如果您已分配了一些内存,那么是否使用free()或delete取决于您用于分配它们的方法。例如,如果您使用了malloc()来分配内存,那么您应该free(),如果您使用new来分配,那么您应该使用delete。但是,请注意不要混合内存分配。使用单一方式分配和取消分配它们。

对于第二个问题,如果不看实际代码,将很难概括。它应该根据具体情况进行。

答案 6 :(得分:1)

所有答案都很好。

在性能问题上,this提供了一种大多数人无法想象的方法,但有些人知道这种方法的效果非常好。

90/10规则属实。根据我的经验,通常有多个故障点,它们通常位于调用堆栈的中间级别。它们通常是由使用过度通用的数据结构引起的,但除非你已经证明它实际上是一个问题,否则你永远不应该修复它。性能问题令人惊讶地无法预测。

修复任何单个性能问题可能无法为您提供所需的加速,但是您修复的每个问题都会使剩余的部分占用剩余时间的更大百分比,因此它们变得更容易找到。加速速度以复合的方式组合,因此您可能会对最终结果感到惊讶。

如果您再也找不到可以修复的重大问题,那么您已经尽力而为。有时,在那时,重新设计(例如使用代码生成)可以引发进一步的加速。