C++ 如何有效地清除 std::queue?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/709146/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I clear the std::queue efficiently?
提问by aJ.
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 类。(基本上这个类以先进先出的方式处理每个作业)。在一种情况下,我想一次性清除队列(从队列中删除所有作业)。我在 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();
}
}
回答by David Rodríguez - dribeas
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)
回答by aJ.
Yes - a bit of a misfeature of the queue class, IMHO. This is what I do:
是的 - 恕我直言,队列类有点错误。这就是我所做的:
#include <queue>
using namespace std;;
int main() {
queue <int> q1;
// stuff
q1 = queue<int>();
}
回答by janis
Author of the topic asked how to clear the queue "efficiently", so I assume he wants better complexity than linear O(queue size). Methods served by David Rodriguez, anonhave the same complexity:
according to STL reference, operator =
has complexity O(queue size).
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 std::queue
is one line:
该主题的作者询问如何“有效地”清除队列,所以我认为他想要比线性O(queue size)更好的复杂性。由David Rodriguez提供的方法,匿名具有相同的复杂性:根据 STL 参考,operator =
具有复杂性O(queue size)。恕我直言,这是因为队列的每个元素都是单独保留的,并且没有像在向量中那样分配在一个大内存块中。所以要清除所有内存,我们必须分别删除每个元素。所以最直接的清除方法std::queue
是一行:
while(!Q.empty()) Q.pop();
回答by tim
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;
}
回答by kolage
In C++11 you can clear the queue by doing this:
在 C++11 中,您可以通过执行以下操作来清除队列:
std::queue<int> queue;
// ...
queue = {};
回答by typ1232
You could create a class that inherits from queue and clear the underlying container directly. This is very efficient.
您可以创建一个继承自 queue 的类并直接清除底层容器。这是非常有效的。
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.
也许您的 a 实现还允许您的 Queue 对象(此处JobQueue
)继承std::queue<Job>
而不是将队列作为成员变量。这样您就可以直接访问c.clear()
您的成员函数。
回答by Dániel László Kovács
Assuming your m_Queue
contains integers:
假设您m_Queue
包含整数:
std::queue<int>().swap(m_Queue)
Otherwise, if it contains e.g. pointers to Job
objects, then:
否则,如果它包含例如指向Job
对象的指针,则:
std::queue<Job*>().swap(m_Queue)
This way you swap an empty queue with your m_Queue
, thus m_Queue
becomes empty.
这样你就可以用你的m_Queue
,交换一个空队列,从而m_Queue
变空。
回答by void.pointer
I do this (Using C++14):
我这样做(使用 C++14):
std::queue<int> myqueue;
myqueue = decltype(myqueue){};
This way is useful if you have a non-trivial queue type that you don't want to build an alias/typedef for. I always make sure to leave a comment around this usage, though, to explain to unsuspecting / maintenance programmers that this isn't crazy, and done in lieu of an actual clear()
method.
如果您不想为其构建别名/typedef 的非平凡队列类型,则这种方式很有用。不过,我总是确保对这种用法发表评论,向毫无戒心的/维护程序员解释这并不疯狂,而是代替了实际clear()
方法。
回答by Marste
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.
我宁愿不依赖swap()
或将队列设置为新创建的队列对象,因为队列元素没有被正确销毁。调用会pop()
调用相应元素对象的析构函数。这在<int>
队列中可能不是问题,但很可能对包含对象的队列产生副作用。
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.
因此,while(!queue.empty()) queue.pop();
不幸的是,如果您想防止可能的副作用,至少对于包含对象的队列来说,循环似乎是最有效的解决方案。
回答by Ronnie
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).
使用 aunique_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