delete []运算符的时间复杂度

时间:2014-01-12 16:27:15

标签: c++ destructor time-complexity delete-operator

delete[]运营商的时间复杂度是什么?

我的意思是它是如何实现的 - 它是否迭代数组中的所有元素并为每个元素调用析构函数?

此运算符是否对原语类型int等)和用户定义的类型执行相同的操作?

4 个答案:

答案 0 :(得分:32)

::operator delete[]记录在cplusplus.com上(有时不赞成):

  

operator delete[]可以作为常规函数显式调用,但在C ++中,delete[]是一个具有非常特定行为的运算符:{{1}的表达式运算符,首先为数组中的每个元素调用适当的析构函数(如果它们是类类型),然后调用函数delete[](即,此功能)释放存储。

所以析构函数被称为 n 次(每个元素一次),然后释放“function”的内存被调用一次。

请注意,每次破坏可能会比其他破坏花费不同的时间(甚至复杂性)。通常,大多数破坏很快,并且具有相同的复杂性......但如果每个被破坏的元素都是复杂的树或节点或图形,情况就不是这样了......

对于像operator delete[]这样的原始类型,int的虚构析构函数是无操作的。编译器可能会优化它(如果被要求)。

您应该检查真正的C++11标准,或者至少是它的晚期n3337工作草案,该草案在§5.3.5.6中说(感谢Matteo Italia在评论中指出) n3337的第110页:

  

如果 delete-expression 的操作数值不是空指针值, delete-expression 将   为对象或要删除的数组的元素调用析构函数(如果有)。在一个案例中   数组,元素将按地址递减的顺序销毁(即完成的顺序相反)   他们的建设者;见12.6.2)

如果你使用-and trust- GCC 4.8或更好,你可以使用带有intg++选项的-fdump-tree-phiopt编译器(注意,他们正在倾销)很多文件!)或MELT插件,用于查询某些示例的中间Gimple表示。或者使用-fdump-tree-all获取汇编程序代码。而且您还想添加优化标记,例如-S -fverbose-asm-O1 ...

注意:恕我直言,cppreference.com也是一个关于C ++的有趣网站,请参阅there关于-O2(由Cubbi评论) < / p>

答案 1 :(得分:8)

deletedelete[]的实施由两个阶段组成:

  1. 递归调用析构函数(如果有的话)
  2. 已删除对象的内存释放
  3. 更不用说对析构函数的调用,其复杂性基本上由你来控制,我们留下了如何释放内存以供考虑。

    第二点不包含在C ++规范中。因此,任何编译器套件/操作系统都可以自由采用自己的策略。

    常见的内存分配/释放策略是在需要时从OS分配整个内存页面,然后在每个new / new[],返回一个适当大小的块,其长度和属性为然后作为页眉/页脚存储在页面内。相应的delete / delete[]可以简单地将相同的块标记为“free”,这显然是O(1)。

    如果内存释放的复杂性为O(1),则delete的复杂性基本上由对析构函数的调用控制。默认实现(几乎)没有,并且它是单个调用的O(1),因此总体 O(n),其中n是调用的转换数量(例如,如果对象是destructed有两个字段,其析构函数被调用,然后是n = 1 (object) + 2 (o. fields) = 3)。

    将所有部分组合在一起:您可以通过在析构函数中执行操作(可以由您编写)来任意增加复杂性,但是您不能“执行更好”¹而不是O(n)(在前一段中定义的n)。 说明这一点的正式方法是:“delete的复杂性是欧米茄(n)”


    ¹让我在这一点上有点不正式

答案 2 :(得分:1)

对于类类型,理论复杂度为O(n)。为每个元素调用析构函数。当然,由实现来遵循可观察行为,因此如果析构函数是无操作或者行为与仅仅将整个块标记为已释放相同,则复杂性可能仅为O(1)

对于原始类型,编译器可能只会立即释放整个内存块,因此复杂度为O(1)

答案 3 :(得分:0)

  

delete[]运算符的时间复杂度是什么?

所需的时间当然是实施定义的。 但是,运算符仅适用于指向1D数组的指针,因此它是O(1)。

  

我的意思是它是如何实现的 - 它是否迭代了所有元素   在数组中并为每个元素调用析构函数?

是。
只要在完全指针上调用它,该指针被分配了使用new[]创建的内存。对于原始类型,没有用户定义的析构函数。

  

此运算符是否对基本类型(int等)执行相同操作   用户定义的类型?

比较不公平,因为原始类型没有用户定义的析构函数,并且它们不能是多态的。
例如,polymorphic class is an undefined behavior上的delete[]。即。

Base* p1 = new Derived, *p2 = new Derived[2];
delete p1; // ok
delete[] p2;  // bad