4

我正在使用 VC 2010 并试图通过将随机定义放置在每个类实例的构造函数中,然后根据需要从那里调用来保持某些函数的开销和重复代码较低。我现在所拥有的,简化的是:

#include <random>
#include <Windows.h>
mt19937 eng(GetTickCount());

class Cycles {
    int line;
    normal_distribution<> rand_norm;
    variate_generator<mt19937&,normal_distribution<>> r_norm;
public:
    Cycles() 
    : rand_norm(0.85,0.05),
      r_norm(eng,rand_norm) { 
        line=0; 
    }
}

不幸的是,这不起作用,我最终得到了这个错误:

\vc\include\random(513): 错误 C2248: 'std::tr1::_Ewrap<_Engine,_Tgt_type>::operator =' : 无法访问在类'std::tr1::_Ewrap<_Engine 中声明的私有成员, _Tgt_type>'

\vc\include\random(446) : 参见 'std::tr1::_Ewrap<_Engine,_Tgt_type>::operator =' 的声明

此诊断发生在编译器生成的函数 'std::tr1::variate_generator<_Engine,_Distrib> &std::tr1::variate_generator<_Engine,_Distrib>::operator =(const std::tr1::variate_generator<_Engine,_Distrib > &)'

我知道这些应该在打开构造函数之前初始化,否则会因为缺少默认构造函数而出错,但我不明白为什么会失败。我的 C++ fu 很生锈。

我看到的每个示例都显示分发器和生成器在调用它的函数中全局或本地初始化,这对我来说似乎很愚蠢,因为我有几个将使用 r_norm 的成员函数在紧密循环中调用。它严重未能通过气味测试。没有人知道我错过了什么吗?

4

3 回答 3

6

bind()在 c++0x 中使用,而不是variate_generator<>

#include <functional> // bind
#include <iostream>
#include <vector>
#include <random>

namespace {
  std::random_device generate_seed;
  std::mt19937 eng(generate_seed());    
  class Cycles {
    int line;
    std::normal_distribution<> rand_norm;
    std::function<double()> r_norm;
  public:
    Cycles(): line(0), rand_norm(0.85, 0.05), r_norm(std::bind(rand_norm, eng))
    {
      // print distribution
      std::vector<size_t> freq(200);
      for (int i = 0; i < 900; ++i) ++freq.at(std::round(r_norm()*100));

      size_t line = 0, max_line = freq.size()-1;
      for ( ; not freq[line] and line <= max_line;  ++line);
      for ( ; not freq[max_line] and max_line >= line; --max_line);
      for ( ; line <= max_line; ++line) {
        std::cout << line << '\t';
        for (size_t j = 0; j < freq[line]; ++j) std::cout << '*';
        std::cout << std::endl;
      }
    }
  };
}    
int main() {
  Cycles c;
}

该图的灵感来自C++0xFAQ

输出

72 **
73 ***
74 ******
75 ********
76 *****************
77 ********************
78 *******************************
79 ************************************************
80 *************************************************
81 **********************************************************
82 ************************************************************
83 ***********************************************************
84 ************************************************************************
85 ********************************************************************************
86 *********************************************************************
87 ************************************************************
88 ****************************************************
89 *************************************
90 **********************************
91 **************************************
92 *************************
93 ******************
94 ********************
95 ************
96 ****
97 **********
98 ***
99 **
100 **
101 *
于 2010-12-16T17:41:20.183 回答
3

手头没有 MSVC,但是使用 gcc,如果您替换,它将编译

variate_generator<mt19937&,normal_distribution<>> r_norm;

variate_generator<mt19937, normal_distribution<> > r_norm;

(注意缺少&

顺便说一句,std::random_device可能是比 更好的随机性来源GetTickCount(),尽管我不知道它是如何在 MSVC 中实现的。

于 2010-10-16T05:13:53.723 回答
-1
mt19937 eng(GetTickCount());

您不能使用非静态表达式初始化全局变量。

于 2010-10-16T04:25:48.843 回答