How do I clear the std::queue efficiently?

后端 未结 11 942
醉梦人生
醉梦人生 2020-12-12 09:10

I am using std::queue for implementing JobQueue class. ( Basically this class process each job in FIFO manner). In one scenario, I want to clear the queue in one shot( delet

相关标签:
11条回答
  • 2020-12-12 09:37

    A common idiom for clearing standard containers is swapping with an empty version of the container:

    void clear( std::queue<int> &q )
    {
       std::queue<int> empty;
       std::swap( q, empty );
    }
    

    It is also the only way of actually clearing the memory held inside some containers (std::vector)

    0 讨论(0)
  • 2020-12-12 09:38

    I'd rather not rely on swap() or setting the queue to a newly created queue object, because the queue elements are not properly destroyed. Calling pop()invokes the destructor for the respective element object. This might not be an issue in <int> queues but might very well have side effects on queues containing objects.

    Therefore a loop with while(!queue.empty()) queue.pop();seems unfortunately to be the most efficient solution at least for queues containing objects if you want to prevent possible side effects.

    0 讨论(0)
  • 2020-12-12 09:38

    Another option is to use a simple hack to get the underlying container std::queue::c and call clear on it. This member must be present in std::queue as per the standard, but is unfortunately protected. The hack here was taken from this answer.

    #include <queue>
    
    template<class ADAPTER>
    typename ADAPTER::container_type& get_container(ADAPTER& a)
    {
        struct hack : ADAPTER
        {
            static typename ADAPTER::container_type& get(ADAPTER& a)
            {
                return a .* &hack::c;
            }
        };
        return hack::get(a);
    }
    
    template<typename T, typename C>
    void clear(std::queue<T,C>& q)
    {
        get_container(q).clear();
    }
    
    #include <iostream>
    int main()
    {
        std::queue<int> q;
        q.push(3);
        q.push(5);
        std::cout << q.size() << '\n';
        clear(q);
        std::cout << q.size() << '\n';
    }
    
    0 讨论(0)
  • 2020-12-12 09:40

    You could create a class that inherits from queue and clear the underlying container directly. This is very efficient.

    template<class T>
    class queue_clearable : public std::queue<T>
    {
    public:
        void clear()
        {
            c.clear();
        }
    };
    

    Maybe your a implementation also allows your Queue object (here JobQueue) to inherit std::queue<Job> instead of having the queue as a member variable. This way you would have direct access to c.clear() in your member functions.

    0 讨论(0)
  • 2020-12-12 09:40

    Using a unique_ptr might be OK.
    You then reset it to obtain an empty queue and release the memory of the first queue. As to the complexity? I'm not sure - but guess it's O(1).

    Possible code:

    typedef queue<int> quint;
    
    unique_ptr<quint> p(new quint);
    
    // ...
    
    p.reset(new quint);  // the old queue has been destroyed and you start afresh with an empty queue
    
    0 讨论(0)
提交回复
热议问题