C++ 恒定正确性和<;随机>;
处理(否则)包含C++11随机类的随机生成器调用的常量函数的正确方法是什么?您是希望放弃函数的常量标志,还是最好将生成器和分发声明为类的可变元素? 最简单的示例(非编译)可能是:C++ 恒定正确性和<;随机>;,c++,c++11,random,constants,mutable,C++,C++11,Random,Constants,Mutable,处理(否则)包含C++11随机类的随机生成器调用的常量函数的正确方法是什么?您是希望放弃函数的常量标志,还是最好将生成器和分发声明为类的可变元素? 最简单的示例(非编译)可能是: #include <random> class foo { std::mt19937 MyGenerator; std::normal_distribution<precision_type> gauss; double get_rnd() const {return gauss
#include <random>
class foo
{
std::mt19937 MyGenerator;
std::normal_distribution<precision_type> gauss;
double get_rnd() const {return gauss(MyGenerator);}
};
#包括
福班
{
标准:mt19937 MyGenerator;
正态分布高斯;
双get_rnd()常量{返回高斯(MyGenerator);}
};
该关键字是为此类案例设计的。使用此修饰符标记random generator实例字段时,即使在封闭类的const
方法中,也允许更改其状态
一般来说,这似乎是一个灰色区域,取决于您的类所代表的概念类型。如果生成器的状态在概念上与此类的状态无关,则此解决方案是可以的。否则,您应该重新考虑设计-如果生成器的状态是相关的,那么使用它的方法不应该是
const
,这实际上取决于您为const
成员访问赋予了什么语义
对于标准类,从多个线程并发调用const
成员是线程安全的。如果让成员const
变异RNG,则会破坏这一点,除非RNG是完全线程安全的(对于非const
使用)
您不必以同样的方式设计类,但是其他开发人员可能会发现发现发现不能同时安全地“读取”(invokeconst
member functions)的类很混乱
一种选择是提供两种变体——使用内部存储的RNG的非常量版本和通过非常量引用接受RNG的
const
版本。(第一个可以调用第二个,无需const\u cast
required)。这实现了“只为您需要的东西付费”准则w.r.t线程安全,因为如果每个线程都提供一个线程本地RNG实例,那么多个线程可以安全地使用该对象。它还允许使用模拟RNG实现进行测试,这可能更有价值。我认为这取决于您的用例。如果您想要一些完全确定的行为,您必须删除const标志以确保您的类的状态不能更改,那么它就不会被更改。如果编写安全相关代码或必须进行可复制测试的代码,这可能很重要。这取决于您想要实现的目标,典型策略包括:
const
可变的;注意线程安全问题(如有必要,即在多线程应用程序中,使用mutable
mutex)
您选择哪种选择取决于您要实现的语义。您能举个小例子吗?如果
random
实例没有试图变异类的任何成员,并且本身不是成员,那么函数仍然可以保持const
@Cyber:根据这个问题,似乎很清楚random
实例是成员(问题称为“元素”)。一个考虑因素可能是线程安全。Const方法通常被视为线程安全的。因此,如果调用受内部互斥体的保护,对我来说,将其变为可变成员似乎是可以的,否则,如果涉及多线程的可能性很小,则不会。如果每次都返回不同的值,则希望将其声明为常量似乎有点奇怪。这会让用户感到困惑。用户希望,如果调用常量对象的方法,它将是幂等的。@Cyber:问题中添加了一个最小的示例。不过,我认为在这种情况下这不是一个好主意mutable
用于帮助实现逻辑上的-const
方法。调用RNG在逻辑上不是-const
@OliverCharlesworth这是一个很好的观点,但是我认为这是一个灰色区域,取决于类所表示的概念(更新了答案)。我假设相同的参数适用于返回当前时间的方法,只要您可以自己为所提供的RNG设定种子(例如,类构造函数允许您提供),那么即使没有模拟,测试也不太成问题,因为您已经确定了。当你希望第六调用返回5中的第一个未返回的特定值时,模拟变得更有价值……在C++中,我们称之为成员函数;BenVoigt:标准确实如此,但口语化的用法似乎更倾向于将“方法”作为一个缩写:)方法这个术语在计算机科学中有其含义。在C++中不加区分地应用它的用户要么来自java,要么有方法,要么没有充分理解C++成员函数不是默认的代码>虚拟<代码>,或者货品编译器只重复他们听到的内容。