为什么std :: list :: pop_front似乎对大型列表来说很慢?

时间:2014-12-19 09:31:17

标签: c++ stdlist

我试图通过在将新节点添加到结尾之前从前面删除节点来限制列表的大小。我期望无论列表大小如何,速度都是恒定的,但我看到更大的列表的执行时间更长。我实现它是错误的,还是pop_front实际上不是恒定的时间?

以下代码执行以下结果:

$ time ./testlist 2 1000000
MAX is 2
NUM is 1000000
DELETED 999998

real    0m0.835s

$ time ./testlist 10 1000000
MAX is 10
NUM is 1000000
DELETED 999990

real    0m1.070s

$ time ./testlist 100 1000000
MAX is 100
NUM is 1000000
DELETED 999900

real    0m3.612s

$ time ./testlist 1000 1000000
MAX is 1000
NUM is 1000000
DELETED 999000

real    0m28.838s

源代码:

#include <iostream>
#include <stdlib.h>
#include <list>

int deletes=0;
std::list<int> l;
void insert(int x, size_t maxsize) {
    if (l.size() == maxsize)
    {
        l.pop_front();
        deletes++;
    }
    l.push_back(x);
}
int main(int argc, char *argv[])
{
    size_t v = atoi(argv[1]);
    size_t n = atoi(argv[2]);
    std::cout << "MAX is " << v << std::endl;
    std::cout << "NUM is " << n << std::endl;
    for (size_t i=0; i<n; i++)
    {
        insert(i, v);
    }
    std::cout << "DELETED " << deletes << std::endl;

    return 0;
}

1 个答案:

答案 0 :(得分:6)

即使在优化版本中,

std::list::size()也需要线性时间(GCC 4.9.2)。请改用:

#include <iostream>
#include <stdlib.h>
#include <list>
#include <deque>

int deletes=0;
int size=0;
std::list<int> l;
void insert(int x, size_t maxsize) {
    if (size == maxsize)
    {
        l.pop_front();
        deletes++;
    size--;
    }
    size++;
    l.push_back(x);
}
int main(int argc, char *argv[])
{
    size_t v = atoi(argv[1]);
    size_t n = atoi(argv[2]);
    std::cout << "MAX is " << v << std::endl;
    std::cout << "NUM is " << n << std::endl;
    for (size_t i=0; i<n; i++)
    {
        insert(i, v);
    }
    std::cout << "DELETED " << deletes << std::endl;

    return 0;
}

注意:deque可能更快(如果实现使用数组,则它们是相同的,但是,deque提供与此list相同的性能 - YMMV )

附录:C ++ 11似乎没有提供O(n)size()的余地,如23.2.1 一般容器要求所述:

  

表达式:a.size()

     

复杂性:常数

在C ++ 11之前,它在这个地方说“常数或线性”,这导致了你在这种情况下的性能问题。

GCC 5.0将解决此问题:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=49561