或对象的任何更改(声明为可变的成员)就对象的用户而言将是原子的。
[我正在从Ivan Čukić中阅读C ++中的函数编程,并且在解释第5章的摘要中的要点时遇到了困难:
,我会对此感到满意。但是,我的这种改写似乎与作者在括号中加上的内容相对应。括号之外的是什么让我感到困惑:该句子中atomic是什么意思?
- [当您创建成员函数
const
时,您保证该函数不会更改类中的任何数据(对象的一点不会改变),或者对对象的任何更改(对于声明的成员就对象的用户而言,mutable
)将是原子的]] ..如果斜体]中的部分仅仅是限于声明为
mutable
的成员
[我正在阅读IvanČukić的C ++函数编程,并且很难解释第5章的摘要中的要点:当使成员函数为const时,可以保证...
] >> < [或对象的任何更改(声明为可变的成员)就对象的用户而言将是原子的。
[我认为这本书的作者(或编辑)在此措辞错了-const
和mutable
不保证线程安全;确实,当语言不支持多线程时,它们就是该语言的一部分(即,当多线程规范不属于C ++标准的一部分时,因此在C ++程序中对多线程所做的任何操作在技术上都是未定义的行为)。]
我认为作者打算传达的是,使用const标记方法对可变成员变量所做的更改应仅限于不更改对象状态的更改
就调用代码所知] >。经典的例子是将昂贵的计算记忆化,以备将来参考,例如:
class ExpensiveResultGenerator
{
public:
ExpensiveResultGenerator()
: _cachedInputValue(-1)
{
}
float CalculateResult(int inputValue) const
{
if ((_cachedInputValue < 0)||(_cachedInputValue != inputValue))
{
_cachedInputValue = inputValue;
_cachedResult = ReallyCPUExpensiveCalculation(inputValue);
}
return _cachedResult;
}
private:
float ReallyCPUExpensiveCalculation(int inputValue) const
{
// Code that is really expensive to calculate the value
// corresponding to (inputValue) goes here....
[...]
return computedResult;
}
mutable int _cachedInputValue;
mutable float _cachedResult;
}
注意,关于使用ExpensiveResultGenerator
类的代码,CalculateResult(int) const
不会更改ExpensiveResultGenerator
对象的状态;它只是在计算数学函数并返回结果。但是在内部,我们正在进行备忘录优化,因此,如果用户连续多次以相同的值调用CalculateResult(x)
来调用x
,则可以在第一次之后跳过昂贵的计算,而只需返回_cachedResult
而是为了加速。当然,进行备忘录优化可以在多线程环境中引入竞争条件,因为现在即使调用代码看不到我们正在更改状态变量,我们也要更改状态变量。因此,为了在多线程环境中安全地执行此操作,您将需要使用某种Mutex来序列化对两个可变变量的访问-或者,或者要求调用代码将对
CalculateResult()
的所有调用序列化。
或对象的任何更改(声明为可变的成员)就对象的用户而言将是原子的。