Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does emptying a std::queue using a scoped queue::swap break any rules?

Tags:

c++

scope

queue

I have a number of situations where queues are being used, which can grow to sizes in the many hundreds. Unfortunately, there is no one-call-solution to emptying the queue, should it become necessary. I'm wondering if using a scoped queue to do a swap, and then let the scoped queue be destroyed, breaks any memory allocation/management rules?

The following snippet is an example of what I am proposing. Seems to work, unsure of results if used many times over long periods.

#include <cstdlib>
#include <iostream>
#include <queue>
int
main()
{
    std::queue<int> foo;
    foo.push(10);
    foo.push(20);
    foo.push(30);
    std::cout << "size of before foo: " << foo.size() << '\n';

    {
        std::queue<int> bar;
        swap(foo, bar);
    }
    std::cout << "size of after foo: " << foo.size() << '\n';
    return 0;
}
like image 252
Weedware Avatar asked May 16 '19 21:05

Weedware


1 Answers

Your code is fine. swap will make foo a default constructed std::queue and when bar is destroyed at the end of the scope it will release the memory that foo was using. Since you aren't using new or delete there is no issue since std::queue "does the right thing" (RAII types are a wonderful thing)

Effectively you've done

std::queue<int>{std::move(foo)}; // move foo into a temporary that is immediately destroyed to release the storage

but your method gives you a stronger guaranteed about the state of foo. Your method leave foo in a default constructed state, while the above method leaves it in a valid, but unspecified state.


Another option is to use one of the solutions provided in Is there a way to access the underlying container of STL container adaptors? to get the underlying container from foo and call clear on it. That would look like

#include <cstdlib>
#include <iostream>
#include <queue>

// function from https://stackoverflow.com/a/29325258/4342498 by jxh: https://stackoverflow.com/users/315052
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);
}

int main()
{
    std::queue<int> foo;
    foo.push(10);
    foo.push(20);
    foo.push(30);
    std::cout << "size of before foo: " << foo.size() << '\n';

    get_container(foo).clear();

    std::cout << "size of after foo: " << foo.size() << '\n';
    return 0;
}
like image 76
NathanOliver Avatar answered Sep 28 '22 01:09

NathanOliver