问题
In this answer on stackoverflow (answer #2) @remyabel recommends this template:
#include <random>
std::mt19937& prng_engine()
{
thread_local static std::random_device rd{};
thread_local static std::mt19937 engine{rd()};
// Or you can replace the two previous lines with:
//thread_local static std::mt19937
// prng{std::random_device{}()};
return engine;
}
template<typename T>
T getRandomNumberBetween(T Min, T Max)
{
thread_local static std::uniform_int_distribution<T> dist{Min, Max};
return dist(prng_engine());
}
Will dist
be created only once for give set of {T, Min, Max
} in thread?
If I call it with (1, 10)
and then with (11, 20)
will it be recreated or not?
回答1:
because it is static, dist is created only once - the first time code flows over it.
The first time code flows over it, the values of Min and Max will be 1 and 10.
On the second call, dist is not re-created so the new values of Min and Max are ignored and you get a random number between 1 and 10.
edit:
here's an implementation of getRandomNumberBetween that does what you want:
template<typename T>
T getRandomNumberBetween(T Min, T Max)
{
using range_t = std::pair<T, T>;
using map_t = std::map<range_t, std::uniform_int_distribution<T>>;
static thread_local map_t range_map;
auto i = range_map.find(range_t(Min, Max));
if (i == std::end(range_map))
{
i = range_map.emplace(std::make_pair(Min, Max), std::uniform_int_distribution<T> { Min, Max}).first;
}
return i->second(prng_engine());
}
回答2:
It will be created only once for every T
(each instantiation of function template has its own copy of local static variables). You can check with:
std::cout << getRandomNumberBetween(0, 1) << '\n'
<< getRandomNumberBetween(10, 20) << '\n'
<< "------------------------\n"
<< getRandomNumberBetween('a', 'b') << '\n'
<< getRandomNumberBetween('c', 'z') << '\n';
Since distribution objects are lightweight, you can simply construct a new distribution when you need a random number (e.g. Vary range of uniform_int_distribution):
template<typename T>
T getRandomNumberBetween(T Min, T Max)
{
std::uniform_int_distribution<T> dist{Min, Max};
return dist(prng_engine());
}
However you can also consider this implementation:
template<typename T>
T getRandomNumberBetween(T Min, T Max)
{
using distribution_type = std::uniform_int_distribution<T>;
using param_type = typename distribution_type::param_type;
thread_local std::uniform_int_distribution<T> dist;
return dist(prng_engine(), param_type(Min, Max));
}
来源:https://stackoverflow.com/questions/30096963/thread-local-static-uniform-int-distribution-will-it-be-recreated-for-different