Basically std::queue
is an Adapter Container - it is not a container by its own, but a thin wrapper around other container.
For example, lets take a look at the queue signature:
template <class T, class Container = deque<T> > class queue;
as you can see, T
is the type of the element stored in the queue, and Container
is the underlying container.
and this is the answer to your question: different containers handles memory differently. the underlying deque may or may not shrink, but it is up to the deque inside to decide.
you can use std::list
as your underlying container as well. in this case, each pop deletes the underlying list node memory.
you can also write your own or modify existing container to match your own memory-management patterns. your container needs to support some methods (such as push_back
, pop_front
) which you can read in the relevant online documentation.
Here is an example to a deque
adapter which shrinks in capacity every 1024 pop
calls:
template<class T>
class DequeAdapter{
private:
std::deque<T> m_Deque;
size_t m_PopCount;
public:
DequeAdapter():
m_PopCount(0){}
bool empty() const noexcept{
return m_Deque.empty();
}
size_t size() const noexcept{
return m_Deque.size();
}
T& front() noexcept{
return m_Deque.front();
}
const T& front()const noexcept{
return m_Deque.front();
}
T& back() noexcept{
return m_Deque.back();
}
const T& back()const noexcept{
return m_Deque.back();
}
void push_back(const T& t){
return m_Deque.push_back(t);
}
void push_back(T&& t){
return m_Deque.push_back(std::move(t));
}
void pop_front(){
m_Deque.pop_front();
m_PopCount++;
if (m_PopCount%1024U == 0U){
m_Deque.shrink_to_fit();
}
}
}
template <class T>
using LeanQueue = std::queue<T,DequeAdapter<T>>;
Do note however, that shrinking in capacity means moving or copying the queue elements to the new lean chunk, the memory consumption will be smaller, but the performance may degrade.