Domanda

According to the cppreference.com reference site on std::shufle, the following method is being deprecated in c++14:

template< class RandomIt >
void random_shuffle( RandomIt first, RandomIt last );

Why will we no longer be able to call the following function without passing a third parameter?

std::random_shuffle(v.begin(),v.end()); //no longer valid in c++14

It doesn't appear as though a different function deceleration has a default parameter set. What is the reason behind this? Was there some kind of alternative added?

È stato utile?

Soluzione

std::random_shuffle may make use, under the hood, of random C family of functions. These functions use global state for seeds and other state.

So it is being deprecated because shuffle will do the same, but better. Namely, it uses the new <random> header from C++11 that doesn't use global state, but its own objects making use of generators, devices and distributions.

Altri suggerimenti

std::random_shuffle is (effectively) replaced by std::shuffle. You do need to pass a third parameter (a random number generator), but in exchange for that you get substantially better definition and (typically) behavior.

std::random_shuffle was fairly poorly defined. It typically used rand() to generate the random numbers, but nothing said whether (and if so how) it called srand, so you couldn't depend (for one example) in rand being seeded how you wanted (and if you seeded it, you couldn't depend on that being put to use). If memory serves, there was also some confusing (and somewhat self-contradictory) language that could be interpreted as saying that random_shuffle couldn't use rand at all, and/or that it couldn't seed it with srand. Even at best, many implementations of rand() were quite poor, so even at very best you couldn't depend on useful results.

Bottom line: random_shuffle is no loss. Use std::shuffle instead, and your code will be much better for it.

We can find the rationale in this document N3775: Deprecating rand and Friends which says:

We therefore now propose to execute the next step of this plan to discourage the use of the traditional C function rand as well as its associated seeding function srand and upper limit macro RAND_MAX.6 In particular, we propose to begin this transition by formally deprecating:

  • rand, srand, and RAND_MAX and
  • algorithm random_shuffle() (keeping shuffle, however).

The rationale for deprecating random_shuffle() is that one overload is specified so as to depend on rand, while the other overload is specified so as to require a hard-to-produce distribution object from the user; such a distribution is already an implicit part of shuffle, which we retain.

and the later document Discouraging rand() in C++14, v2 which reiterates this position.

Update

As Howard Hinnant notes N3775 has an error: rand_shuffle() is allowed but not required to use rand() under the hood but that would not change the rationale.

random_shuffle is being deprecated because its RNG is unspecified -- not just that you don't have to specify it, but that the standard itself doesn't specify it. On VC++, for instance, it uses rand(), which is implemented really poorly!

The other responses answer the question, but if anyone is looking for some cut-n-paste code that may suit your needs, the following will probably do the trick:

#include <random>
...
std::random_device rd;
std::mt19937 g(rd());
std::shuffle(v.begin(), v.end(), g);

rd yields non-deterministic random data on many platforms and the generator g uses a Mersenne Twister pseudo-random generator with a large state.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top