当前位置:  开发笔记 > 编程语言 > 正文

如何有效清除std :: queue?

如何解决《如何有效清除std::queue?》经验,为你挑选了5个好方法。

我正在使用std :: queue来实现JobQueue类.(基本上这个类以FIFO方式处理每个作业).在一种情况下,我想一次性清除队列(从队列中删除所有作业).我没有看到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();
    }
}

David Rodríg.. 246

清除标准容器的常用习惯是使用容器的空版本进行交换:

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

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



1> David Rodríg..:

清除标准容器的常用习惯是使用容器的空版本进行交换:

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

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


更好的是`std :: queue ().swap(q)`.使用复制和交换习惯用法,所有这些都应该等同于`q = std :: queue ()`.
虽然`std :: queue ().swap(q)`等同于上面的代码,但`q = std :: queue ()`不一定是等价的.由于在分配的内存的分配中没有所有权的转移,一些容器(如vector)可能只调用先前保持的元素的析构函数并设置*size*(或使用存储的指针的等效操作)而不实际释放内存.
@ThorbjørnLindeijer:从原始队列的用户的角度来看,这些元素不存在.你是正确的,因为它们将被一个接一个地销毁并且成本是线性的,但是除了本地函数之外的任何其他人都无法访问它们.在多线程环境中,您将锁定,将非临时队列与原始队列交换,解锁(以允许并发访问)并让交换的队列死亡.这样,您可以在关键部分之外移动销毁成本.
`queue`没有`swap(other)`方法,所以`queue ().swap(q)`不编译.我认为你必须使用通用的`swap(a,b)`.
@ThorbjørnLindeijer:在C++ 03中你是对的,在C++ 11队列中有*swap*作为成员函数,另外还有一个自由函数重载,它将交换两个相同类型的队列.

2> 小智..:

是的 - 有点像队列类的错误,恕我直言.这就是我做的:

#include 
using namespace std;;

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


使用新的C++,只需`q1 = {}`即可
`q1 = queue ();`既短又清楚(你不是_really_试图`.swap`,你试图`.clear`).
@Naszta请详细说明`swap`是如何"更有效"
@Ari语法(2)在[list_initialization](https://en.cppreference.com/w/cpp/language/list_initialization)和(10)在[operator_assignment](https://en.cppreference.com/w/ cpp /语言/ operator_assignment)。默认的queue <T>构造函数与空参数列表`{}`匹配并且是隐式的,因此被调用,然后`q1.operator =(queue <T> &&)`消耗新创建的`queue`。

3> 小智..:

'David Rodriguez','anon'该主题的作者询问如何"有效地"清除队列,因此我认为他希望复杂性高于线性O(队列大小).您提供的方法具有相同的复杂性:根据stl引用,operator =具有复杂度O(队列大小).恕我直言,因为队列的每个元素都是单独保留的,并且它不会分配在一个大的内存块中,就像在向量中一样.因此,为了清除所有内存,我们必须分别删除每个元素.所以最明确的方法operator =是一行:

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


如果您使用实际数据,则不能只查看操作的O复杂性.如果线性操作的常数使得它比所有的"n <2 ^ 64"的二次方程慢,我会采用"O(n ^ 2)"算法而不是"O(n)"算法,除非我有一些强大的有理由相信我必须搜索IPv6地址空间或其他一些特定问题.现实中的表现对我来说比对极限的表现更重要.
这个答案比公认的答案更好,因为内部队列在被销毁时仍会这样做。因此,可接受的答案是O(n),它还会对全新队列进行额外的分配和初始化。

4> tim..:

显然,有两种最明显的方法可以清除std::queue:交换空对象和分配给空对象.

我建议使用赋值,因为它更快,更易读,更明确.

我使用以下简单代码测量性能,我发现在C++ 03版本中交换比分配给空对象慢70-80%.但是,在C++ 11中,性能没有差别.无论如何,我会去任务.

#include 
#include 
#include 
#include 
#include 

int main()
{
    std::cout << "Started" << std::endl;

    std::queue q;

    for (int i = 0; i < 10000; ++i)
    {
        q.push(i);
    }

    std::vector > queues(10000, q);

    const std::clock_t begin = std::clock();

    for (std::vector::size_type i = 0; i < queues.size(); ++i)
    {
        // OK in all versions
        queues[i] = std::queue();

        // OK since C++11
        // std::queue().swap(queues[i]);

        // OK before C++11 but slow
        // std::queue empty;
        // std::swap(empty, queues[i]);
    }

    const double elapsed = double(clock() - begin) / CLOCKS_PER_SEC;

    std::cout << elapsed << std::endl;

    return 0;
}



5> kolage..:

在C ++ 11中,您可以通过执行以下操作清除队列:

std::queue queue;
// ...
queue = {};

推荐阅读
Chloemw
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有