我正在使用std :: queue来实现JobQueue类。 (基本上这个类以FIFO方式处理每个作业)。 在一种情况下,我想一次性清除队列(从队列中删除所有作业)。 我没有看到std :: queue class中有任何明确的方法。
如何有效地为JobQueue类实现clear方法?
我有一个简单的循环播放解决方案,但我正在寻找更好的方法。
//Clears the job queue
void JobQueue ::clearJobs()
{
// I want to avoid pop in a loop
while (!m_Queue.empty())
{
m_Queue.pop();
}
}
答案 0 :(得分:232)
清除标准容器的常用习惯是使用容器的空版本进行交换:
void clear( std::queue<int> &q )
{
std::queue<int> empty;
std::swap( q, empty );
}
它也是实际清除某些容器(std :: vector)
中保存的内存的唯一方法答案 1 :(得分:41)
是的 - 有点像队列类的错误,恕我直言。这就是我的工作:
#include <queue>
using namespace std;;
int main() {
queue <int> q1;
// stuff
q1 = queue<int>();
}
答案 2 :(得分:21)
stl::queue
的方法就是一行:
while(!Q.empty()) Q.pop();
答案 3 :(得分:13)
显然,有两种最明显的方法可以清除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;
}
答案 4 :(得分:5)
在C ++ 11中,您可以通过执行以下操作清除队列:
$scope.totalPrice = 0;
$scope.items = [{
"item": "phone",
"desc": "Iphone 4",
"price": 100,
"qty": 1
}, {
"item": "phone",
"desc": "Iphone 5",
"price": 200,
"qty": 2
}, {
"item": "phone",
"desc": "Iphone 6",
"price": 300,
"qty": 3
}, {
"item": "phone",
"desc": "Iphone 7",
"price": 400,
"qty": 1
}];
$scope.updatePrice = function() {
var total = 0;
angular.forEach($scope.items, function(item) {
total += item.qty * item.price;
});
$scope.totalPrice = total;
};
$scope.updatePrice();
答案 5 :(得分:4)
您可以创建一个从队列继承并直接清除基础容器的类。这非常有效。
template<class T>
class queue_clearable : public std::queue<T>
{
public:
void clear()
{
c.clear();
}
};
也许您的实现还允许您的Queue对象(此处为JobQueue
)继承std::queue<Job>
,而不是将队列作为成员变量。这样,您就可以直接访问成员函数中的c.clear()
。
答案 6 :(得分:1)
我宁愿不依赖swap()
或将队列设置为新创建的队列对象,因为队列元素没有被正确销毁。调用pop()
会调用相应元素对象的析构函数。这可能不是<int>
队列中的问题,但可能会对包含对象的队列产生副作用。
因此,如果您想要防止可能出现的副作用,至少对于包含对象的队列来说,带有while(!queue.empty()) queue.pop();
的循环似乎是最有效的解决方案。
答案 7 :(得分:1)
假设您的m_Queue
包含整数:
std::queue<int>().swap(m_Queue)
否则,如果包含例如指向Job
对象的指针,然后:
std::queue<Job*>().swap(m_Queue)
通过这种方式,您与m_Queue
交换了一个空队列,因此m_Queue
变为空。
答案 8 :(得分:0)
使用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
答案 9 :(得分:0)
我这样做(使用C ++ 14):
std::queue<int> myqueue;
myqueue = decltype(myqueue){};
如果您不想为它构建别名/ typedef的非平凡队列类型,这种方法很有用。不过,我总是确保对这种用法发表评论,以向毫不怀疑/维护的程序员解释这并不疯狂,并且代替了实际的clear()
方法。
答案 10 :(得分:0)
另一种选择是使用简单的技巧来获取基础容器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';
}