Я изучаю C ++, и я прочитал это: Если элемент данных объявляется изменяемым, то можно присвоить значение этому элементу данных из функции-члена const.
Но следующий код скомпилирован без каких-либо ошибок или предупреждений от gcc.
(Это не реальный пример кода, я просто написал его, чтобы проверить ключевое слово mutable)
class M
{
public:
M(){x=10;};
int getX() {x++; return x;};
private:
mutable int x;
};
int main()
{
M xx;
std::cout << xx.getX() << std::endl;
}
Разве я не должен объявлять getX как const?
Правка 1 (ответ ForEver проясняет ситуацию), следующий код не будет скомпилирован:
class M
{
public:
M(){x=10;};
int getX() const {x++; return x;};
private:
int x;
};
int main()
{
M xx;
std::cout << xx.getX() << std::endl;
}
Законно изменять изменяемые файлы в const
функции и, конечно, законно изменять изменяемые файлы в non-const
функции (как каждый non-const member-variable
). mutable
Ключевое слово позволяет изменять переменную в const
функции, но не дает никаких ограничений на изменение в non-const
функции.
mutable
обычно используется, чтобы позволить const
квалифицированные функции-члены для изменения кэшированных данных. Вы можете объявить getX()
как const
и счастливо изменить x
вот для чего изменяем. Однако обычно считается плохой идеей модифицировать внутреннее состояние объекта в функции-члене, которая по своему объявлению говорит, что это не так.
Например, у вас есть функция-член const, которая вычисляет значение на основе содержимого контейнера. Если в контейнере много элементов, получение результата может занять много времени. Если результат изменяется только при добавлении или удалении элементов из контейнера, вы можете кэшировать его для дальнейшего использования. Поскольку функция-член квалифицирована как const, вам необходимо объявить переменную результата как mutable
, Поскольку результат может быть рассчитан на основе существующих данных в контейнере, кэшированное значение не считается частью внутреннего состояния объекта, и считается допустимым изменить его с помощью функции const.
int Foo::CalcResult() const
{
if(hasValidCache_ == false)
{
// ... recalc value ...
// Cache the result
hasValidCache = true;
cachedValue_ result;
}
return cachedValue_;
}
Утверждение означает это.
class M
{
public:
M(){x=10;};
int getX() const
// ^^^^^ If a member function is const...
{x++; return x;};
// ^^^ ...and it modifies a member variable...
private:
mutable int x;
// ^^^^^^^ ...then that variable must be mutable.
};