или что любые изменения в объекте (для членов, объявленных как изменяемые) будут atomi c с точки зрения пользователей объекта.
Я думаю, что автор (или редактор) книги плохо сформулировал свое утверждение там - const
и mutable
не дают никаких гарантий относительно безопасности потоков; действительно, они были частью языка еще тогда, когда в языке не было поддержки многопоточности (то есть, когда спецификации многопоточности не были частью стандарта C ++, и поэтому все, что вы делали с многопоточностью в своей программе на C ++, было технически неопределенным поведением).
Я думаю, что автор намеревался передать, что изменения изменяемых переменных-членов из метода с тегами const должны быть ограничены только изменениями, которые не меняют состояние объекта до вызывающего кода могу сказать . Примером classi c этого может быть запоминание дорогостоящих вычислений для использования в будущем, например:
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()
.