最近我决定试用新的c ++ 11随机库,有一件事让我想到......从容器中挑选随机元素时摆脱[rand()%nelemennts]。原因是我想要可重复生成,当使用rand封装是不存在的,因为
auto set_a=generateSet(nelements1); //generateSet calls rand
auto set_b=generateSet(nelements2); //so set_b is determined by the previous line :(
所以这就是我提出的: (注意,这不是线程安全的,它设计为安全的方式,调用generateSet不会影响彼此(通过改变rand内部值的状态))
template<typename container_type,typename element_type >
class RandElemGetter
{
const container_type& containter_ref;
std::uniform_int_distribution<size_t> distribution;
std::mt19937 engine;
public:
RandElemGetter(container_type& container): containter_ref(container),distribution(0,container.size()-1)
{
}
element_type get()
{
return containter_ref[distribution(engine)];
}
};
用法:
{
vector<int> v{1,2,3,1701,1729};
vector<int> result;
RandElemGetter<vector<int>,int> reg_v(v);
for(size_t i=0;i<nelements;++i)
result.push_back(reg_v.get());
}
这是可行的解决方案吗?我知道它不是线程安全的,这不是重点。我想知道是否有更好的“范围”方式从随机访问容器中获取随机元素。可以使用std :: advance对所有人进行修改。
答案 0 :(得分:2)
RandElemGetter(container_type container):
containter_ref(container),distribution(0,container.size()-1)
这将按值获取容器,创建临时副本,并存储对该副本的引用。一旦构造函数完成,引用就无效了。
您需要存储副本,或通过引用传递参数。最后通过常量引用传递复杂对象是个好主意,以避免不必要的复制。
答案 1 :(得分:1)
<typename container_type, typename value_type = container_type::typename value_type>
。 STL容器的value_types有typedef,所以通常不需要重复自己。*std::advance(containter_ref.begin(), distribution(engine));
get()
重命名为operator()
,并提供result_type
typedef以符合STL模型AdaptableGenerator 您可能希望从原始STL获得SGI random_sample
的峰值;我相信GNU仍然将其作为扩展。