如何有效地清除 std::queue ?
我正在使用 std::queue 来实现 JobQueue 类。 (基本上这个类以先进先出的方式处理每个作业)。 在一种情况下,我想一次性清除队列(从队列中删除所有作业)。 我在 std::queue 类中没有看到任何明确的方法可用。
如何有效地实现 JobQueue 类的clear方法?
我有一个简单的循环弹出解决方案,但我正在寻找更好的方法。
//Clears the job queue
void JobQueue ::clearJobs()
{
// I want to avoid pop in a loop
while (!m_Queue.empty())
{
m_Queue.pop();
}
}
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.
How do I efficiently implement the clear method for JobQueue class ?
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();
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
清除标准容器的常见习惯用法是与容器的空版本进行交换:
这也是实际清除某些容器(std::vector)内保存的内存的唯一方法
A common idiom for clearing standard containers is swapping with an empty version of the container:
It is also the only way of actually clearing the memory held inside some containers (std::vector)
是的 - 队列类有点错误,恕我直言。 这就是我所做的:
Yes - a bit of a misfeature of the queue class, IMHO. This is what I do:
在 C++11 中,您可以通过执行以下操作来清除队列:
In C++11 you can clear the queue by doing this:
该主题的作者询问如何“有效”地清除队列,因此我假设他想要比线性O(队列大小)更好的复杂性。 由 David Rodriguez、 提供的方法anon 具有相同的复杂性:
根据 STL 参考,
operator =
的复杂度为 O(queue size)。恕我直言,这是因为队列的每个元素都是单独保留的,并且它没有像向量一样分配在一个大内存块中。 因此,要清除所有内存,我们必须分别删除每个元素。 因此,清除 std::queue 的最直接方法是一行:
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, anon have 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:显然,有两种最明显的方法可以清除 std::queue:与空对象交换和分配给空对象。
我建议使用赋值,因为它更快、更具可读性并且更明确。
我使用以下简单代码测量了性能,发现 C++03 版本中的交换比分配给空对象慢 70-80%。 然而,在 C++11 中,性能没有差异。 不管怎样,我会去完成任务。
Apparently, there are two most obvious ways to clear
std::queue
: swapping with empty object and assignment to empty object.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.
您可以创建一个继承自队列的类并直接清除底层容器。 这是非常有效的。
也许您的实现还允许您的 Queue 对象(此处为 JobQueue)继承 std::queue而不是将队列作为成员变量。 这样您就可以在成员函数中直接访问
c.clear()
。You could create a class that inherits from queue and clear the underlying container directly. This is very efficient.
Maybe your a implementation also allows your Queue object (here
JobQueue
) to inheritstd::queue<Job>
instead of having the queue as a member variable. This way you would have direct access toc.clear()
in your member functions.假设您的
m_Queue
包含整数:否则,如果它包含指向
Job
对象的指针,则:这样您就可以将空队列与您的
m_Queue
交换,因此m_Queue
变空。Assuming your
m_Queue
contains integers:Otherwise, if it contains e.g. pointers to
Job
objects, then:This way you swap an empty queue with your
m_Queue
, thusm_Queue
becomes empty.我这样做(使用 C++14):
如果您有一个不平凡的队列类型,并且不想为其构建别名/typedef,则这种方法很有用。 不过,我总是确保围绕此用法留下评论,以向毫无戒心的/维护程序员解释这并不疯狂,并且是代替实际的
clear()
方法完成的。I do this (Using C++14):
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.我不想依赖
swap()
或将队列设置为新创建的队列对象,因为队列元素没有正确销毁。 调用 pop() 会调用相应元素对象的析构函数。 这在
队列中可能不是问题,但很可能会对包含对象的队列产生副作用。因此,如果您想防止可能的副作用,则使用 while(!queue.empty())queue.pop(); 的循环似乎是最有效的解决方案,至少对于包含对象的队列而言是如此。
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. Callingpop()
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.使用
unique_ptr
可能没问题。然后重置它以获得一个空队列并释放第一个队列的内存。
至于复杂度? 我不确定 - 但猜想是 O(1)。
可能的代码:
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:
另一种选择是使用简单的 hack 来获取底层容器
std::queue::c
并对其调用clear
。 根据标准,该成员必须存在于std::queue
中,但不幸的是受保护
。 这里的黑客取自这个答案。Another option is to use a simple hack to get the underlying container
std::queue::c
and callclear
on it. This member must be present instd::queue
as per the standard, but is unfortunatelyprotected
. The hack here was taken from this answer.交换并不比“=”更有效。 。
交换只需使用 std::move 即可。 但对于空队列,std::move 是没有用的。
我的队列=空队列; 或 my_queue = std::move(empty_queue);
swap is not more efficient than "=". .
swap just use std::move. but for empty queue, std::move is useless.
my_queue = empty_queue; or my_queue = std::move(empty_queue);