std :: queue를 효율적으로 지우려면 어떻게해야합니까?
JobQueue 클래스를 구현하기 위해 std :: queue를 사용하고 있습니다. 기본적으로이 클래스는 각 작업을 FIFO 방식으로 처리합니다. 한 시나리오에서 한 번에 대기열을 지우고 싶습니다 (대기열에서 모든 작업 삭제). std :: queue 클래스에서 사용할 수있는 명확한 방법이 없습니다.
JobQueue 클래스에 대한 명확한 메소드를 효율적으로 구현하는 방법은 무엇입니까?
루프에서 터지는 간단한 솔루션이 있지만 더 나은 방법을 찾고 있습니다.
//Clears the job queue
void JobQueue ::clearJobs()
{
// I want to avoid pop in a loop
while (!m_Queue.empty())
{
m_Queue.pop();
}
}
표준 컨테이너를 지우는 일반적인 관용구는 빈 버전의 컨테이너로 바꾸는 것입니다.
void clear( std::queue<int> &q )
{
std::queue<int> empty;
std::swap( q, empty );
}
또한 일부 컨테이너 (std :: vector) 안에있는 메모리를 실제로 지우는 유일한 방법입니다
예-대기열 클래스 IMHO의 약간의 잘못된 기능. 이것이 제가하는 것입니다:
#include <queue>
using namespace std;;
int main() {
queue <int> q1;
// stuff
q1 = queue<int>();
}
주제의 저자는 큐를 "효율적으로"지우는 방법을 물었으므로 linear O (queue size) 보다 더 복잡한 것을 원한다고 가정 합니다. 에 의해 제공 방법 데이비드 로드리게스 , 아논가 동일한 복잡성을 가지고 STL 기준에 따른 operator =
복잡도 갖는다 O (큐 사이즈) . IMHO 큐의 각 요소는 별도로 예약되어 있으며 벡터와 같이 하나의 큰 메모리 블록에 할당되지 않기 때문입니다. 따라서 모든 메모리를 지우려면 모든 요소를 개별적으로 삭제해야합니다. 따라서 가장 명확한 방법 std::queue
은 한 줄입니다.
while(!Q.empty()) Q.pop();
분명히 분명한 두 가지 분명한 방법이 있습니다 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;
}
C ++ 11에서는 다음을 수행하여 큐를 지울 수 있습니다.
std::queue<int> queue;
// ...
queue = {};
큐에서 상속하는 클래스를 만들고 기본 컨테이너를 직접 지울 수 있습니다. 이것은 매우 효율적입니다.
template<class T>
class queue_clearable : public std::queue<T>
{
public:
void clear()
{
c.clear();
}
};
어쩌면 구현 에서 큐를 멤버 변수로 사용하는 대신 Queue 객체 (here JobQueue
)를 상속 할 수도 있습니다 std::queue<Job>
. 이렇게하면 c.clear()
멤버 함수에서 직접 액세스 할 수 있습니다.
m_Queue
정수를 포함 한다고 가정하면 :
std::queue<int>().swap(m_Queue)
그렇지 않으면, 예를 들어 Job
객체에 대한 포인터가 포함 된 경우 :
std::queue<Job*>().swap(m_Queue)
This way you swap an empty queue with your m_Queue
, thus m_Queue
becomes empty.
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.
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.
I do this (Using 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.
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:
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
Another option is to use a simple hack to get the underlying container std::queue::c
and call clear
on it. This member must be present in std::queue
as per the standard, but is unfortunately protected
. The hack here was taken from 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';
}
참고URL : https://stackoverflow.com/questions/709146/how-do-i-clear-the-stdqueue-efficiently
'Programing' 카테고리의 다른 글
passport.js RESTful 인증 (0) | 2020.06.07 |
---|---|
QLabel : 텍스트 및 배경색 설정 (0) | 2020.06.07 |
명령 줄에서 스크립트로 함수 실행 (노드 JS) (0) | 2020.06.05 |
중단 점을 없애려면 어떻게해야합니까? (0) | 2020.06.05 |
라텍스로 URL을 작성하는 방법? (0) | 2020.06.05 |