简体   繁体   中英

Time difference between swap and pop for for std::queue remove all of element

I'm trying to clear std::queue so that there are already some posing about this. How do I clear the std::queue efficiently?

I've tried to make a simple code for this. I have a question for time difference between "swap" and just "pop" method.

Test1 and Test2 are same total time. However, inside of method result is different.

CASE Test1: queue pop

  Wed Jul 22 11:33:33 2015 : 10000000 start queue Wed Jul 22 11:33:38 2015 : 10000000 queue push complete diff : 5592 milliseconds(msec) Wed Jul 22 11:33:38 2015 : 10000000 clear queue Wed Jul 22 11:33:42 2015 : 10000000 queue clear complete diff : 3561 milliseconds(msec) diff between after TEST1 : 135644 milliseconds(msec) 

CASE Test2: queue swap

  Wed Jul 22 11:37:45 2015 : 10000000 start queue Wed Jul 22 11:37:51 2015 : 10000000 queue push complete diff : 5875 milliseconds(msec) Wed Jul 22 11:37:51 2015 : 10000000 clear queue Wed Jul 22 11:40:00 2015 : 10000000 queue clear complete diff : 129130 milliseconds(msec) diff between after TEST2 : 135006 milliseconds(msec) 

Is there any reason why it works?

Environment: Windows7 (x64), MSVC2013

Code snippet:

#include <iostream>
#include <exception>
#include <chrono>
#include <queue>
#include <vector>
#include <ctime>
#include <string>

using namespace std;

std::string asString(const std::chrono::system_clock::time_point& tp)
{
    std::time_t t = std::chrono::system_clock::to_time_t(tp);
    std::string ts = std::ctime(&t);
    ts.resize(ts.size() - 1);
    return ts;
}

template<class T>
void clear(std::queue<T> &q)
{
    std::queue<T> empty;
    std::swap(q, empty);
}

void Test1(int itemCount, int mode)
{
    queue<int> q;
    std::chrono::system_clock::time_point tp_push = std::chrono::system_clock::now();
    std::cout << asString(tp_push) << " : " << itemCount << " start queue : mode - " << mode << endl;

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

    std::cout << asString(std::chrono::system_clock::now()) << " : " << itemCount << " queue push complete " << endl;
    auto diff_push = std::chrono::system_clock::now() - tp_push;
    std::cout << " diff : "
        << chrono::duration_cast<chrono::milliseconds>(diff_push).count()
        << " milliseconds(msec) " << endl;

    std::chrono::system_clock::time_point tp_clear = std::chrono::system_clock::now();
    std::cout << asString(tp_clear) << " : " << itemCount << " clear queue " << endl;

    if (mode)
    {
        clear(q);
    }
    else
    {
        while (!q.empty())
        {
        q.pop();
        }
    }

    std::cout << asString(std::chrono::system_clock::now()) << " : " << itemCount << " queue clear complete " << endl;
    auto diff_clear = std::chrono::system_clock::now() - tp_clear;
    std::cout   << " diff : "
                    << chrono::duration_cast<chrono::milliseconds>(diff_clear).count()
                    << " milliseconds(msec) " << endl;
}

int main()
{
    try 
    {
        int itemCount = 10000000;

        std::chrono::system_clock::time_point tp_test1 = std::chrono::system_clock::now();

        Test1(itemCount, 0);  

        auto diff_test1 = std::chrono::system_clock::now() - tp_test1;
        std::cout << " diff between after TEST1 : "
            << chrono::duration_cast<chrono::milliseconds>(diff_test1).count()
            << " milliseconds(msec) " << endl;

        std::chrono::system_clock::time_point tp_test2 = std::chrono::system_clock::now();

        Test1(itemCount, 1);

        auto diff_test2 = std::chrono::system_clock::now() - tp_test2;
        std::cout << " diff after TEST2 : "
            << chrono::duration_cast<chrono::milliseconds>(diff_test2).count()
            << " milliseconds(msec) " << endl;


    }
    catch (const exception& e)
    {
        cerr << "EXCEPTION : " << e.what() << endl;
    }
}

It looks like std::queue when swapped does the equivalent of while()/pop(). This is especially true if the underlying structure is a linked list, as it would have to be iterated over each element to free up the memory.

The reason swap appears to do the same thing as the while/pop loop is because you've 'moved' the data from an empty queue into your queue object (and vice versa) - your queue object is now empty, but all you've done is move the data into a temporary queue object that is immediately freed once the Clear function returns, due to the automatic scoping of empty resulting in its descructor being called.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM