我应该保留随机分发对象实例还是可以随时重新创建它?

时间:2011-12-08 15:31:50

标签: c++ random c++11

我有这段代码:

static std::mt19937 rnd;

// ...

static uint32_t rndInt(uint32_t min, uint32_t max) {
    return std::uniform_int_distribution<uint32_t>(min,max)(rnd);
}

这是一种好的做法,还是应该存储uniform_int_distribution

3 个答案:

答案 0 :(得分:9)

我怀疑分发对象的创建和销毁成本很高,尽管我认为它可能只是存储参数min,max。它可能会根据参数预先计算一些有用的值,例如在明显的实现中2**32 % (max-min+1)是生成器中将被丢弃和重新尝试的不同值的数量。

原则上,允许分发对象在其中存储一些熵,这些熵是在先前调用operator()时从生成器中提取的,但不是必需的。这些位可用于稍后的operator()调用。因此,如果min==0max==1,那么您可以在生成器上每次调用的分配上对operator()进行32次调用。这就是reset()函数的用途,以清除这种状态。

因此,如果您重复使用相同的最小值/最大值,那么从技术上讲,每次使用新的分布都会浪费随机位 - 与保留分发对象相比,最终可能会减少对引擎的调用周围。但我怀疑这很重要,特别是因为MT很快。

答案 1 :(得分:1)

我通常会做以下事情:

std::uniform_int_distribution<uint32_t> distrib(16, 97);

然后,您可以多次调用distrib(rnd),而不必每次都重新生成分发。

执行操作的方式会强制每次拨打电话时重新创建分发。如果你的最小和最大参数是固定的,那么创建一个分配对象并调用它,否则,保持你拥有的。

BTW,我会使用rnd或其他种子方法播种time(NULL)

答案 2 :(得分:0)

熵存储在std::mt19937中,这意味着您将继续随机序列,但正如Steve Jessop所指出的,它仍然有一些创建对象的开销。如果您希望使用相同的参数频繁调用此函数,则可以在使用std::uniform_int_distribution<uint32_t>作为键的映射中缓存std::pair<uint32_t, uint32_t>个对象。