Efficient linked list in C++?

后端 未结 11 651
孤街浪徒
孤街浪徒 2021-02-02 06:36

This document says std::list is inefficient:

std::list is an extremely inefficient class that is rarely useful. It performs a heap allocation

11条回答
  •  无人及你
    2021-02-02 07:02

    Thanks for all the answers. This is a simple - though not rigorous - benchmark.

    // list.cc
    #include 
    using namespace std;
    
    int main() {
        for (size_t k = 0; k < 1e5; k++) {
            list ln;
            for (size_t i = 0; i < 200; i++) {
                ln.insert(ln.begin(), i);
                if (i != 0 && i % 20 == 0) {
                    ln.erase(++++++++++ln.begin());
                }
            }
        }
    }
    

    and

    // vector.cc
    #include 
    using namespace std;
    
    int main() {
        for (size_t k = 0; k < 1e5; k++) {
            vector vn;
            for (size_t i = 0; i < 200; i++) {
                vn.insert(vn.begin(), i);
                if (i != 0 && i % 20 == 0) {
                    vn.erase(++++++++++vn.begin());
                }
            }
        }
    }
    

    This test aims to test what std::list claims to excel at - O(1) inserting and erasing. And, because of the positions I ask to insert/delete, this race is heavily skewed against std::vector, because it has to shift all the following elements (hence O(n)), while std::list doesn't need to do that.

    Now I compile them.

    clang++ list.cc -o list
    clang++ vector.cc -o vector
    

    And test the runtime. The result is:

      time ./list
      ./list  4.01s user 0.05s system 91% cpu 4.455 total
      time ./vector
      ./vector  1.93s user 0.04s system 78% cpu 2.506 total
    

    std::vector has won.

    Compiled with optimization O3, std::vector still wins.

      time ./list
      ./list  2.36s user 0.01s system 91% cpu 2.598 total
      time ./vector
      ./vector  0.58s user 0.00s system 50% cpu 1.168 total
    

    std::list has to call heap allocation for each element, while std::vector can allocate heap memory in batch (though it might be implementation-dependent), hence std::list's insert/delete has a higher constant factor, though it is O(1).

    No wonder this document says

    std::vector is well loved and respected.

    EDIT: std::deque does even better in some cases, at least for this task.

    // deque.cc
    #include 
    using namespace std;
    
    int main() {
        for (size_t k = 0; k < 1e5; k++) {
            deque dn;
            for (size_t i = 0; i < 200; i++) {
                dn.insert(dn.begin(), i);
                if (i != 0 && i % 20 == 0) {
                    dn.erase(++++++++++dn.begin());
                }
            }
        }
    }
    

    Without optimization:

    ./deque  2.13s user 0.01s system 86% cpu 2.470 total
    

    Optimized with O3:

    ./deque  0.27s user 0.00s system 50% cpu 0.551 total
    

提交回复
热议问题