Имеет ли ключевое слово mutable какую-либо цель, кроме возможности изменения переменной с помощью const-функции? - PullRequest
494 голосов
/ 19 сентября 2008

Некоторое время назад я наткнулся на некоторый код, который помечал переменную-член класса с ключевым словом mutable. Насколько я вижу, это просто позволяет вам изменить переменную в методе const:

class Foo  
{  
private:  
    mutable bool done_;  
public:  
    void doSomething() const { ...; done_ = true; }  
};

Это единственное использование этого ключевого слова или это больше, чем кажется на первый взгляд? С тех пор я использовал эту технику в классе, помечая boost::mutex как изменяемое, позволяя const функциям блокировать его по соображениям безопасности потоков, но, честно говоря, это похоже на хак.

Ответы [ 18 ]

3 голосов
/ 14 января 2014

Используйте «mutable», когда для вещей, которые ЛОГИЧЕСКИ не сохраняют состояние для пользователя (и, следовательно, должны иметь «const» геттеры в API-интерфейсах открытого класса), но НЕ являются безлимитными в базовой реализации (код в .cpp).

Случаи, которые я использую чаще всего, - это ленивая инициализация членов "простых старых данных" без состояния. А именно, он идеален в узких случаях, когда такие элементы дороги либо для сборки (процессор), либо для переноса (память), и многие пользователи объекта никогда не будут запрашивать их. В этой ситуации вы хотите ленивую конструкцию на стороне сервера для повышения производительности, поскольку 90% созданных объектов вообще не нужно будет создавать их, но вам все равно нужно представить правильный API без сохранения состояния для общего пользования.

1 голос
/ 25 января 2015

Один из лучших примеров, где мы используем mutable, - это глубокая копия. в конструкторе копирования мы отправляем const &obj в качестве аргумента. Таким образом, новый созданный объект будет иметь постоянный тип. Если мы хотим изменить (в основном мы не будем изменять, в редких случаях мы можем изменить) элементы этого вновь созданного объекта const, нам нужно объявить его как mutable.

mutable класс хранения может использоваться только для не статических неконстантных данных класса. Изменяемый член данных класса может быть изменен, даже если он является частью объекта, который объявлен как const.

class Test
{
public:
    Test(): x(1), y(1) {};
    mutable int x;
    int y;
};

int main()
{
    const Test object;
    object.x = 123;
    //object.y = 123;
    /* 
    * The above line if uncommented, will create compilation error.
    */   

    cout<< "X:"<< object.x << ", Y:" << object.y;
    return 0;
}

Output:-
X:123, Y:1

В приведенном выше примере мы можем изменить значение переменной-члена x, хотя она является частью объекта, который объявлен как const. Это потому, что переменная x объявлена ​​как изменяемая. Но если вы попытаетесь изменить значение переменной-члена y, компилятор выдаст ошибку.

1 голос
/ 24 июля 2014

Изменяемое меняет значение const с битового const на логическое const для класса.

Это означает, что классы с изменяемыми членами больше не являются побитовыми const и больше не будут появляться в секциях исполняемого файла, доступных только для чтения.

Кроме того, он изменяет проверку типов, позволяя const функциям-членам изменять изменяемые элементы без использования const_cast.

class Logical {
    mutable int var;

public:
    Logical(): var(0) {}
    void set(int x) const { var = x; }
};

class Bitwise {
    int var;

public:
    Bitwise(): var(0) {}
    void set(int x) const {
        const_cast<Bitwise*>(this)->var = x;
    }
};

const Logical logical; // Not put in read-only.
const Bitwise bitwise; // Likely put in read-only.

int main(void)
{
    logical.set(5); // Well defined.
    bitwise.set(5); // Undefined.
}

См. Другие ответы для получения более подробной информации, но я хотел бы подчеркнуть, что это не просто для безопасности типов и что это влияет на скомпилированный результат.

1 голос
/ 27 мая 2014

Ключевое слово mutable очень полезно при создании заглушек для целей тестирования класса. Вы можете заглушить функцию const и при этом иметь возможность увеличивать (изменяемые) счетчики или любую тестовую функциональность, которую вы добавили в свою заглушку. Это сохраняет интерфейс класса заглушки нетронутым.

1 голос
/ 01 февраля 2014

Изменяемая таблица может быть полезна, когда вы переопределяете виртуальную функцию const и хотите изменить переменную члена дочернего класса в этой функции. В большинстве случаев вы не захотите изменять интерфейс базового класса, поэтому вы должны использовать собственную переменную-член с изменяемыми параметрами.

1 голос
/ 16 мая 2011

Классический пример (как упоминалось в других ответах) и единственная ситуация, в которой я видел ключевое слово mutable, использовавшееся до сих пор, - это кэширование результата сложного метода Get, где кэш реализован как член данных класса, а не как статическая переменная в методе (по причинам совместного использования несколькими функциями или простой чистоты).

Как правило, альтернативой использованию ключевого слова mutable обычно является статическая переменная в методе или трюк const_cast.

Другое подробное объяснение в здесь .

1 голос
/ 20 сентября 2008

В некоторых случаях (например, плохо спроектированные итераторы) класс должен сохранять счетчик или другое случайное значение, которое не влияет на основное «состояние» класса. Это чаще всего, где я вижу изменчивое использование. Без изменчивости вы были бы вынуждены пожертвовать всем постоянством вашего дизайна.

В большинстве случаев мне кажется, что это хак. Полезно в очень немногих ситуациях.

0 голосов
/ 22 февраля 2014

Само ключевое слово 'mutable' на самом деле является зарезервированным ключевым словом. Часто оно используется для изменения значения постоянной переменной. Если вы хотите иметь несколько значений constsnt, используйте ключевое слово mutable.

//Prototype 
class tag_name{
                :
                :
                mutable var_name;
                :
                :
               };   
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...