代码之家  ›  专栏  ›  技术社区  ›  aJ.

如何有效地清除std::队列?

  •  140
  • aJ.  · 技术社区  · 16 年前

    在一个场景中,我希望一次性清除队列(从队列中删除所有作业)。

    如何有效地为JobQueue类实现clear方法?

    我有一个简单的解决方案,但我正在寻找更好的方法。

    //Clears the job queue
    void JobQueue ::clearJobs()
     {
      // I want to avoid pop in a loop
        while (!m_Queue.empty())
        {
            m_Queue.pop();
        }
    }
    
    11 回复  |  直到 4 年前
        1
  •  286
  •   David Rodríguez - dribeas    16 年前

    清除标准容器的一个常见习惯用法是与空版本的容器交换:

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

    这也是实际清除某些容器(std::vector)中存储的内存的唯一方法

        2
  •  51
  •   Mark Ransom    11 年前

    #include <queue>
    using namespace std;;
    
    int main() {
        queue <int> q1;
        // stuff
        q1 = queue<int>();  
    }
    
        3
  •  32
  •   Melebius    5 年前

    该主题的作者问如何“有效地”清除队列,所以我认为他想要比线性队列更好的复杂性 O(队列大小) . 提供服务的方法 David Rodriguez , anon 具有相同的复杂性: operator = 具有复杂性 . std::queue 有一行:

    while(!Q.empty()) Q.pop();
    
        4
  •  19
  •   tim    10 年前

    std::queue :与空对象交换并分配给空对象。

    我使用下面的简单代码测量了性能,发现在C++03版本中进行交换比分配给空对象慢70-80%。然而,在C++11中,性能没有差别。不管怎么说,我会同意这个任务。

    #include <algorithm>
    #include <ctime>
    #include <iostream>
    #include <queue>
    #include <vector>
    
    int main()
    {
        std::cout << "Started" << std::endl;
    
        std::queue<int> q;
    
        for (int i = 0; i < 10000; ++i)
        {
            q.push(i);
        }
    
        std::vector<std::queue<int> > queues(10000, q);
    
        const std::clock_t begin = std::clock();
    
        for (std::vector<int>::size_type i = 0; i < queues.size(); ++i)
        {
            // OK in all versions
            queues[i] = std::queue<int>();
    
            // OK since C++11
            // std::queue<int>().swap(queues[i]);
    
            // OK before C++11 but slow
            // std::queue<int> empty;
            // std::swap(empty, queues[i]);
        }
    
        const double elapsed = double(clock() - begin) / CLOCKS_PER_SEC;
    
        std::cout << elapsed << std::endl;
    
        return 0;
    }
    
        5
  •  13
  •   Danny_ds    6 年前

    在C++11中,可以通过以下操作清除队列:

    std::queue<int> queue;
    // ...
    queue = {};
    
        6
  •  5
  •   typ1232    11 年前

    您可以创建一个从队列继承的类,并直接清除底层容器。这是非常有效的。

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

    JobQueue )承继 std::queue<Job> 而不是将队列作为成员变量。这样您就可以直接访问 c.clear()

        7
  •  3
  •   Dániel László Kovács    6 年前

    假设你 m_Queue 包含整数:

    std::queue<int>().swap(m_Queue)
    

    Job 对象,然后:

    std::queue<Job*>().swap(m_Queue)
    

    这样,您就可以将一个空队列与 排队 排队 变成空的。

        8
  •  2
  •   Marste    11 年前

    swap() 或者将队列设置为新创建的队列对象,因为队列元素未正确销毁。使命感 pop() <int>

    因此,使用 while(!queue.empty()) queue.pop();

        9
  •  2
  •   void.pointer    6 年前

    我这样做(使用C++14):

    std::queue<int> myqueue;
    myqueue = decltype(myqueue){};
    

    如果您有一个不想为其构建别名/typedef的非平凡队列类型,这种方法非常有用。不过,我总是会在这个用法上留下评论,向毫无戒心的/维护程序员解释,这并不疯狂,而是代替了实际使用 clear() 方法

        10
  •  1
  •   display name    10 年前

    使用 unique_ptr
    然后重置它以获得一个空队列,并释放第一个队列的内存。 至于复杂性呢?我不确定,但我猜是O(1)。

    可能代码:

    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
    
        11
  •  1
  •   Ruslan PiotrNycz    6 年前

    另一种选择是使用简单的hack来获取底层容器 std::queue::c clear 在上面。该成员必须出席会议 std::queue 按照标准,但不幸的是 protected . 这里的黑客是从 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';
    }