我有一个从一组字母表中生成随机字符的功能。这个函数会被多次调用,因此我试图让它使用相同的变量集,即具有相同的种子,以便字符串不会尽可能长地重复。
#include <iostream>
#include <random>
#include <string>
std::string generateRandomChar(const unsigned int _len)
{
std::string result;
result.reserve(_len);
static constexpr char alphanum[] = "0123456789"
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(0, 61);
for (int i = 0; i < _len;
result += (alphanum[dis(gen)]);
}
return result;
}
int main(){
for(int i = 0; i < 10; ++i){
std::cout << generateRandomChar(10) << std::endl;
}
}
不幸的是我对c ++ 11函数没有任何专业知识,我之前只使用srand
和朋友,所以我可能在这里犯了很多错误。目前它工作并生成大量的字符串而不重复,但我相信我可以制作 -
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(0, 61);
也是静态变量,因此每次调用函数时都不会计算它,因为这样会浪费吗?
那么哪一个应该是静态的呢?你在这里看到任何错误/改进吗?
谢谢你:D
编辑 - 这是一个ideone链接 - http://ideone.com/e7ssXo
答案 0 :(得分:2)
那么哪一个应该是静态的?
std::mt19937 gen
或其中没有一个。
std::random_device
使用非确定性熵源生成均匀分布的随机整数(如果可用)。您的代码使用std::random_device
输出作为std::mt19937
伪随机生成器的种子。因此,如果你在PC上运行,你很可能会为std::mt19937
提供良好的,非确定性的种子,因此不需要将它们中的任何一个静态化。我认为std::random_device
仅在低端控制器上实现为纯程序PRNG。
另一方面,一次性播种更具惯用性,因此您可以将std::mt19937
声明为静态。 std::mt19937
本身实现了具有19937位状态的高质量PRNG算法,因此如果生成器在现代PC上运行,它的周期可能超过Universe生命周期(或至少stelliferous era)。 / p>
不需要使std::uniform_int_distribution
静态,因为它只是一个根据所需分布属性修改实际生成器输出的包装器。因此,您可以自行决定是否将其设为静态。
答案 1 :(得分:1)
您可以将random_device
和mt19937
设为静态。目前你每次调用函数时都会构建一个函数(IIRC,mt19937
构造成本很高。有人核心我)。此外,您的uniform_int_distribution
可以移出循环。这个问题更适合代码审查,因为它已经有效并且您正在寻求改进。
TL; DR:你可以使它们全部静止。
答案 2 :(得分:1)
为了允许单元测试,我建议将发生器移出函数之外,如
std::string generateRandomChar(const unsigned int len, std::mt19937& gen)
{
std::string result;
result.reserve(len);
static constexpr char alphanum[] = "0123456789"
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
std::uniform_int_distribution<> dis(0, 61);
for (int i = 0; i < len; ++i) {
result += (alphanum[dis(gen)]);
}
return result;
}
int main() {
std::random_device rd;
std::mt19937 gen(rd());
for (int i = 0; i < 10; ++i) {
std::cout << generateRandomChar(10, gen) << std::endl;
}
}
或创建一个类
class RandomCharGenerator
{
public:
RandomCharGenerator() : RandomCharGenerator(std::random_device{}()) {}
template <typename T>
RandomCharGenerator(T&& seed) : gen(std::forward<T>(seed)) {}
std::string operator() (const unsigned int len)
{
std::string result;
result.reserve(len);
for (int i = 0; i < len; ++i) {
result += (alphanum[dis(gen)]);
}
return result;
}
private:
std::mt19937 gen;
std::uniform_int_distribution<> dis{0, 61};
static constexpr char alphanum[] = "0123456789"
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
};
int main() {
RandomCharGenerator charGenerator{};
for (int i = 0; i < 10; ++i) {
std::cout << charGenerator(10) << std::endl;
}
}
你最终可以模仿事物以允许其他兰特生成器。