恒定的正确性和<random>

use*_*865 10 c++ random const mutable c++11

处理(否则)包含C++ 11随机类的随机生成器调用的常量函数的正确方法是什么?您是否应该放弃函数的常量标志,还是将生成器和分布声明为类的可变元素?一个最小的例子(不编译)可能是:

#include <random>

class foo 
{
  std::mt19937 MyGenerator;
  std::normal_distribution<precision_type> gauss;
  double get_rnd() const {return gauss(MyGenerator);}
};
Run Code Online (Sandbox Code Playgroud)

Ben*_*igt 11

这实际上取决于您为const成员访问提供的语义.

对于标准类,const从多个线程同时调用成员是线程安全的.const除非RNG完全是线程安全的(不const使用),否则让RNG变异的成员会破坏这一点.

您不必以相同的方式设计类,但其他开发人员可能会发现发现无法安全地"读取"(同时调用const成员函数)的类会让人感到困惑.

一种选择是提供两种变体 - 使用内部存储的RNG的非const版本,以及const通过非const引用接受RNG 的版本.(第一个可以调用第二个,const_cast不需要).这实现了"仅根据需要付费"指导线程安全性,因为如果每个线程都提供线程本地RNG实例,则多个线程可以安全地使用该对象.它还允许使用模拟RNG实现进行测试,这可能更有价值.


Mat*_* M. 6

这取决于你想要达到的目标,典型的策略包括:

  1. 揭露可变性.只是不要将方法标记为const.

  2. 外化以暴露可变性.将可变元素(这里是生成器和分布)作为方法参数传递,暴露内部使用可变性,调用者负责任何线程安全隐含.

  3. 实现"逻辑"常量.如果不考虑使用随机性破坏类的逻辑常量,则可以简单地将生成器和分布声明为mutable; 注意线程安全的影响(如果需要,即在多线程应用程序中,使用mutable互斥锁)

您选择哪种替代方案取决于您要实现的语义.

  • @BenVoigt:标准确实如此,但口语用法似乎偏向"方法"作为一个简单的:) (7认同)
  • 术语*方法*在计算机科学中具有意义.在C++中不加选择地应用它的用户要么来自Java,要么*有方法,并且还没有完全弄清楚C++成员函数不是"虚拟" - 默认情况下,或货物崇拜程序员只是重复他们听到的内容. (3认同)
  • 我个人喜欢非虚拟参数调用代码段这个术语 (2认同)