在类中随机使用 C++0x TR1,以降低开销

发布于 2024-09-28 05:10:22 字数 1156 浏览 0 评论 0原文

我正在使用 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 的成员函数。它严重未通过气味测试。没有人知道我错过了什么吗?

I'm using VC 2010 and trying to keep the overhead and duplicated code of certain functions low, by placing the random definitions in the constructor of each class instance, then calling as necessary from there. What I have now, simplified, is:

#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; 
    }
}

Unfortunately that doesn't work, and I end up with this error:

\vc\include\random(513): error C2248: 'std::tr1::_Ewrap<_Engine,_Tgt_type>::operator =' : cannot access private member declared in class 'std::tr1::_Ewrap<_Engine,_Tgt_type>'

\vc\include\random(446) : see declaration of 'std::tr1::_Ewrap<_Engine,_Tgt_type>::operator ='

This diagnostic occurred in the compiler generated function 'std::tr1::variate_generator<_Engine,_Distrib> &std::tr1::variate_generator<_Engine,_Distrib>::operator =(const std::tr1::variate_generator<_Engine,_Distrib> &)'

I understand that these should be initialized prior to the opening of the constructor, or else it errors because of the lack of a default constructor, but I don't understand why this fails. My C++ fu is quite rusty.

Every example I've seen shows the distributor and generator being initialized globally or locally in the function that calls it, which seems silly to me, as I have several member functions that will be using r_norm that are called in a tight loop. It fails the smell test badly. Doesn't anyone know what I'm missing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

书信已泛黄 2024-10-05 05:10:22

c++0x 中使用 bind() 而不是 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 *

bind() is used in c++0x instead of 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;
}

The plot is inspired by C++0xFAQ.

Output

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 *
︶ ̄淡然 2024-10-05 05:10:22

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

variate_generator<mt19937&,normal_distribution<>> r_norm;

variate_generator<mt19937, normal_distribution<> > r_norm;

(注意缺少 &),

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

don't have MSVC at hand, but with gcc, this will compile if you replace

variate_generator<mt19937&,normal_distribution<>> r_norm;

with

variate_generator<mt19937, normal_distribution<> > r_norm;

(note the lack of &)

Incidentally, std::random_device is probably a better source of randomness than GetTickCount(), although I don't know how it's implemented in MSVC.

掐死时间 2024-10-05 05:10:22
mt19937 eng(GetTickCount());

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

mt19937 eng(GetTickCount());

You cannot initialize a global variable with a non-static expression.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文