std::vector<void*>::保留 O(1) 时间操作的参数是什么?

For what argument is std::vector<void*>::reserve an O(1) time operation?

本文关键字:操作 时间 参数 是什么 保留 void lt vector gt std      更新时间:2023-10-16

我想知道以下问题的大致答案:

int n;
...
std::vector<void*> vectorOfPointers;
vectorOfPointers.reserve(n);
0 (1)中,上述程序最多运行到哪个数字n ?

让我们假设对于一台运行32位Ubuntu和3gb内存的笔记本电脑,不运行任何其他程序。是几万、几千还是几百万?一个人需要知道什么信息才能回答这样的问题?有没有一种不用实验就能知道的方法?

我从来没有研究过操作系统,但在我的想象中,操作系统分配内存只需要2步。它决定了块开始的指针和块结束的指针。情况可能会更加复杂,因为系统可能必须进行清理,以便获得足够大的内存块。但是,如果我们假设系统只运行这一个程序,我们如何估计所需的时间?除了内存碎片之外,还有其他方面需要考虑吗?

编辑:

对不起,我没有把我的问题说清楚。需要注意的是,在调用reserve之前vector是空的,因此不需要复制数据。

从c++的角度来看,代码占用O(1)时间(它在当前容器的大小中是线性的,在您的情况下始终为零)。

现在,看起来你的问题实际上是关于分配m字节内存的复杂性。这恐怕是没有说明的。

有关进一步的讨论,请参见内存分配的时间复杂度

在前面的问题上再补充一点,这里有几个层次的复杂性:

  • 首先,malloc()需要维护其内部数据结构。这样做的复杂性没有指定,但是人们希望malloc(m)不会占用Θ(m)的时间。然而,复杂性很可能取决于其他因素,例如内存碎片。其次,malloc()可能需要从操作系统请求额外的内存。在这里,期望操作系统对它分配的每个内存页做一些事情(例如擦除它,这样你就不会看到其他人的机密数据)并不是不合理的。如果发生这种情况,操作确实是Θ(m)

使用reserve()时不能依赖于0(1)复杂度。

复杂性

容器大小线性

(cf cppreference)

基本上,新内存的分配是在常数时间内,但是你还需要将旧元素从以前的内存复制到新的内存中(因此线性复杂性)。

因此,在空向量上,保留可能有一个常数时间,但我不确定标准是否明确说明了这一点。所以这可能取决于底层的实现(即使我没有看到任何不这样做的理由)。

唯一的O(1)我能想到的std::vector::reserve()是当n <= capacity(),这意味着reserve()不做任何事情。