delete[]运算符的时间复杂性
Time complexity of delete[] operator
delete[]
运算符的时间复杂性是什么?
我的意思是它是如何实现的——它是否迭代数组中的所有元素,并为每个元素调用析构函数?
该运算符对基元类型(int
等)和用户定义的类型执行相同操作吗?
::operator delete[]
在cplusplus.com上被记录为:
operator delete[]
可以作为正则函数显式调用,但在C++中,delete[]
是一个具有非常特定行为的运算符:一个具有delete[]
运算符的表达式,首先为数组中的每个元素调用适当的析构函数(如果这些元素属于类类型),然后调用函数operator delete[]
(即此函数)来释放存储。
因此析构函数被调用n次(每个元素一次),然后释放内存的"函数"被调用一次。
请注意,每次销毁可能需要与其他销毁不同的时间(甚至复杂程度)。一般来说,大多数破坏都很快,并且具有相同的复杂性。。。。但如果每个被破坏的元素都是一个复杂的树、节点或图,情况就不是这样了
对于像int
这样的基元类型,int
的假想析构函数是no-op。编译器可能会对此进行优化(如果需要的话)。
您应该查看真正的C++11标准,或者至少是其最新的n3337工作草案,该草案在n3337:第110页§5.3.5.6中写道(感谢Matteo Italia在评论中指出)
如果删除表达式的操作数值不是空指针值,则delete表达式
如果您使用并足够信任GCC 4.8或更好的版本,您可以使用带有-fdump-tree-phiopt
或-fdump-tree-all
选项的g++
编译器(注意,它们正在转储大量文件!)或MELT插件来查询某些示例的中间Gimple表示。或者使用-S -fverbose-asm
来获得汇编代码。您还想添加优化标志,如-O1
或-O2
。。。
NB:IMHO,cppreference.com也是一个关于C++的有趣网站,请参阅delete
(如Cubbi所评论)
delete
和delete[]
的实现由两个阶段组成:
- 对析构函数的递归调用(如果有的话)
- 已删除对象的内存释放
更不用说对析构函数的调用链了,它的复杂性基本上由您决定,我们只剩下如何释放内存来考虑。
C++规范没有涉及第二点。因此,任何编译器套件/OS都可以自由地采用自己的策略。
常见的内存分配/释放策略是在需要时从OS分配整个内存页,然后在每个new
/new[]
返回适当大小的块,然后将其长度和属性作为页眉/页脚存储在页面内。对应的delete
/delete[]
可以简单到将同一块标记为"空闲",这显然是O(1)。
如果内存释放的复杂性是O(1),那么delete
的复杂性本质上由对析构函数的调用控制。默认实现(几乎)什么都不做,对于单个调用是O(1),因此是一个整体O(n),其中n是调用的总数(例如,如果被析构函数的对象有两个字段调用了析构函数,则为n = 1 (object) + 2 (o. fields) = 3
)。
把所有的部分放在一起:你可以通过在析构函数(可以由你编写)中执行操作来任意增加复杂性,但你不能比O(n)(上一段中定义的n)"执行得更好">正式正确的表述方式是:"delete
的复杂性是Omega(n)">。
请允许我在这一点上有点非正式
对于类类型,理论复杂度为O(n)
。为每个元素调用析构函数。当然,这取决于实现是否遵守可观察的行为,因此,如果析构函数是无操作的,或者行为与仅将整个块标记为已释放的行为相同,则复杂性可能仅为O(1)
。
对于基元类型,编译器可能会一次释放整个内存块,因此复杂性为O(1)
。
delete[]
运算符的时间复杂度是多少?
所需的时间量当然是由实现定义的然而,运算符仅适用于指向1D数组的指针,因此它是O(1)
我的意思是它是如何实现的——它是否迭代所有元素并为每个元素调用析构函数?
是
前提是它只在精确指针上调用,该指针被分配了一个使用new[]
创建的内存。对于基元类型,没有用户定义的析构函数。
这个运算符对基元类型(int等)和用户定义的类型?
这种比较是不公平的,因为基元类型没有用户定义的析构函数,它们不能是polymorhpic
例如,多态类上的delete[]
是未定义的行为。即
Base* p1 = new Derived, *p2 = new Derived[2];
delete p1; // ok
delete[] p2; // bad
- 具有未知值时的时间复杂性
- 使用堆查找第K个最大元素的时间复杂性
- 解决这个问题的时间复杂性是多少
- 如果你有一个固定大小的数组,你需要遍历它!n次,使用二进制搜索如何改变时间复杂性
- 对于像C++这样的现实世界语言,时间复杂性有什么一致的定义吗
- 两个嵌套循环的运行时间复杂性:二次型还是线性
- 是平衡二进制树上预购和DFS的时间复杂性
- 带有多个内部回路的循环的时间复杂性
- 列表STL的时间复杂性在一段时间内进行排序
- O(2M N)和O(kN)的时间复杂性
- 映射向量的时间复杂性是多少
- 时间复杂性差异以及如何
- 递归最糟糕的情况时间复杂性
- 可传递值影响递归算法的渐近时间复杂性
- 程序的时间复杂性确定两个字符串是否彼此排列
- 为什么此代码O(n)的时间复杂性
- next_perMuart的时间复杂性在大o符号中
- C 中使用了哪种类型的堆以及STD :: Pirstity_queue的时间复杂性
- 带有两个递归调用的递归算法的时间复杂性
- delete[]运算符的时间复杂性