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

时间:2022-03-07 15:01:11

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( delete all jobs from the queue). I don't see any clear method available in std::queue class.

我使用std::queue来实现JobQueue类。(基本上这门课是按FIFO的方式进行的)。在一个场景中,我希望一次性清空队列(从队列中删除所有作业)。在std中我没有看到任何清晰的方法::queue类。

How do I efficiently implement the clear method for JobQueue class ?

如何高效地实现JobQueue类的clear方法?

I have one simple solution of popping in a loop but I am looking for better ways.

我有一个简单的方法,可以在一个循环中弹出,但是我正在寻找更好的方法。

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

8 个解决方案

#1


199  

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)

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

#2


34  

Yes - a bit of a misfeature of the queue class, IMHO. This is what I do:

是的——队列类的一个错误特性,IMHO。这就是我所做的:

#include <queue>
using namespace std;;

int main() {
    queue <int> q1;
    // stuff
    q1 = queue<int>();  
}

#3


12  

'David Rodriguez', 'anon' Author of the topic asked how to clear the queue "efficiently", so I assume he wants better complexity than linear O(size of queue). Methods that you served have the same complexity: according to stl reference, operator = has complexity O(size of queue). IMHO it's because each element of queue is reserved separately and it isn't allocated in one big memory block, like in vector. So to clear all memory, we have to delete every element separately. So the straightest way to clear stl::queue is one line:

“大卫·罗德里格斯”,“不久”主题的作者问如何清除队列“有效地”,所以我认为他想要比线性复杂度O(队列)的大小。你曾有相同的复杂性方法:根据stl参考,操作符=复杂度O(队列的大小)。IMHO是因为的每个元素分配队列分别保留并不是在一个大的内存块,像在向量。为了清除所有内存,我们必须分别删除每个元素。所以最直的方式清楚stl:队列是一行:

while(!Q.empty()) Q.pop();

#4


7  

Apparently, there are two most obvious ways to clear std::queue: swapping with empty object and assignment to empty object.

显然,有两种最明显的方法可以清除std::queue:将空对象和赋值转换为空对象。

I would suggest using assignment because it simply faster, more readable, and unambiguous.

我建议使用赋值,因为它更快、更可读、更明确。

I measured performance using following simple code and I found that swapping in C++03 version works 70-80% slower than assignment to an empty object. In C++11 there is no difference in performance, however. Anyway, I would go with assignment.

我使用下面的简单代码来测量性能,我发现在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


3  

In C++11 you can clear the queue by doing this:

在c++ 11中,可以这样做:

std::queue<int> queue = {};

#6


2  

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.

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

#7


1  

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.

我不希望依赖交换()或将队列设置为新创建的队列对象,因为队列元素没有被正确地销毁。调用pop()调用相应元素对象的析构函数。在 队列中,这可能不是问题,但可能对包含对象的队列有副作用。

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.

因此,如果想要防止可能的副作用,至少对于包含对象的队列来说,这是最有效的解决方案。

#8


0  

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).

使用unique_ptr可能是可以的。然后重新设置它以获得空队列并释放第一个队列的内存。的复杂性?我不确定——但我猜是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

#1


199  

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)

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

#2


34  

Yes - a bit of a misfeature of the queue class, IMHO. This is what I do:

是的——队列类的一个错误特性,IMHO。这就是我所做的:

#include <queue>
using namespace std;;

int main() {
    queue <int> q1;
    // stuff
    q1 = queue<int>();  
}

#3


12  

'David Rodriguez', 'anon' Author of the topic asked how to clear the queue "efficiently", so I assume he wants better complexity than linear O(size of queue). Methods that you served have the same complexity: according to stl reference, operator = has complexity O(size of queue). IMHO it's because each element of queue is reserved separately and it isn't allocated in one big memory block, like in vector. So to clear all memory, we have to delete every element separately. So the straightest way to clear stl::queue is one line:

“大卫·罗德里格斯”,“不久”主题的作者问如何清除队列“有效地”,所以我认为他想要比线性复杂度O(队列)的大小。你曾有相同的复杂性方法:根据stl参考,操作符=复杂度O(队列的大小)。IMHO是因为的每个元素分配队列分别保留并不是在一个大的内存块,像在向量。为了清除所有内存,我们必须分别删除每个元素。所以最直的方式清楚stl:队列是一行:

while(!Q.empty()) Q.pop();

#4


7  

Apparently, there are two most obvious ways to clear std::queue: swapping with empty object and assignment to empty object.

显然,有两种最明显的方法可以清除std::queue:将空对象和赋值转换为空对象。

I would suggest using assignment because it simply faster, more readable, and unambiguous.

我建议使用赋值,因为它更快、更可读、更明确。

I measured performance using following simple code and I found that swapping in C++03 version works 70-80% slower than assignment to an empty object. In C++11 there is no difference in performance, however. Anyway, I would go with assignment.

我使用下面的简单代码来测量性能,我发现在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


3  

In C++11 you can clear the queue by doing this:

在c++ 11中,可以这样做:

std::queue<int> queue = {};

#6


2  

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.

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

#7


1  

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.

我不希望依赖交换()或将队列设置为新创建的队列对象,因为队列元素没有被正确地销毁。调用pop()调用相应元素对象的析构函数。在 队列中,这可能不是问题,但可能对包含对象的队列有副作用。

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.

因此,如果想要防止可能的副作用,至少对于包含对象的队列来说,这是最有效的解决方案。

#8


0  

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).

使用unique_ptr可能是可以的。然后重新设置它以获得空队列并释放第一个队列的内存。的复杂性?我不确定——但我猜是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