c++shufflestdvector

How to shuffle a std::vector?


I am looking for a generic, reusable way to shuffle a std::vector in C++. This is how I currently do it, but I think it's not very efficient because it needs an intermediate array and it needs to know the item type (DeckCard in this example):

srand(time(NULL));

cards_.clear();

while (temp.size() > 0) {
    int idx = rand() % temp.size();
    DeckCard* card = temp[idx];
    cards_.push_back(card);
    temp.erase(temp.begin() + idx);
}

Solution

  • Since C++20, we have

    #include <algorithm>
    #include <random>
    
    auto rng = std::default_random_engine {};
    std::ranges::shuffle(cards_, rng);
    

    For C++11 to C++17, it's slightly more verbose:

    #include <algorithm>
    #include <random>
    
    auto rng = std::default_random_engine {};
    std::shuffle(std::begin(cards_), std::end(cards_), rng);
    

    Live example on Coliru

    Make sure to reuse the same instance of rng throughout multiple calls to std::shuffle if you intend to generate different permutations every time!

    Moreover, if you want your program to create different sequences of shuffles each time it is run, you can seed the constructor of the random engine with the output of std::random_device:

    auto rd = std::random_device {}; 
    auto rng = std::default_random_engine { rd() };
    

    If you're stuck with C++98, you may use:

    #include <algorithm>
    
    std::random_shuffle(cards_.begin(), cards_.end());
    

    Avoid this for new code, though: std::random_shuffle() was removed in C++20.