我使用std::queue实现JobQueue类。(基本上这个类以FIFO方式处理每个作业)。 在一个场景中,我希望一次性清除队列(从队列中删除所有作业)。 我在std::queue类中没有看到任何可用的清除方法。

如何有效地实现JobQueue类的清除方法?

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

//Clears the job queue
void JobQueue ::clearJobs()
 {
  // I want to avoid pop in a loop
    while (!m_Queue.empty())
    {
        m_Queue.pop();
    }
}

当前回答

显然,有两种最明显的方法来清除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;
}

其他回答

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

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

也许你的a实现也允许你的Queue对象(这里是JobQueue)继承std:: Queue <Job>,而不是将Queue作为成员变量。这样就可以在成员函数中直接访问c.clear()。

清除标准容器的一个常用习语是交换容器的空版本:

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

它也是清除某些容器内内存的唯一方法(std::vector)

我宁愿不依赖swap()或将队列设置为新创建的队列对象,因为队列元素没有正确地销毁。调用pop()调用各自元素对象的析构函数。这在<int>队列中可能不是问题,但可能会对包含对象的队列产生副作用。

因此,如果您想防止可能的副作用,那么使用while(!queue.empty()) queue.pop();进行循环似乎是最有效的解决方案,至少对于包含对象的队列是如此。

显然,有两种最明显的方法来清除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;
}

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

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

如果您有一个不平凡的队列类型,并且不想为其构建别名/typedef,则这种方法非常有用。不过,我总是确保就这种用法留下评论,向不知情的/维护程序员解释这并不疯狂,并代替了实际的clear()方法。