Ir para o conteúdo

Última atualização:2026-10-12

A palavra-chave mutable em C++

Um mergulho profundo na palavra-chave mutable em C++

Em C++, a palavra-chave mutable é frequentemente vista como uma ferramenta para "atravessar" a restrição de constância (const). Em certas situações, embora queiramos impor proteção de constância a um objeto, ainda precisamos modificar alguns dos seus membros de dados. Este artigo explora em detalhes os cenários de uso de mutable e a filosofia de design por trás dele, e discute como ele resolve necessidades específicas de programação em C++.

1. Uso básico da palavra-chave mutable

Sabemos que, quando uma função membro é modificada por const, ela garante que não modificará o estado do objeto. Na prática, porém, às vezes queremos modificar um membro de dados e ainda assim manter a função membro marcada como const. É aqui que entra a palavra-chave mutable:

class Foo  
{  
private:  
    mutable bool done_;  
public:  
    void doSomething() const {
        // 在 const 成员函数中修改 mutable 成员
        done_ = true;
    }  
};

No exemplo acima, doSomething() é declarada como const, indicando que ela não altera o estado do objeto. No entanto, done_ está marcado como mutable, o que significa que podemos modificar done_ mesmo dentro de um método const. Esse design permite gerenciar certos dados que precisam ser modificados mantendo inalterada a semântica da interface da função.

2. Constância lógica vs. constância de bits

A constância em C++ pode ser dividida em dois tipos: constância lógica e constância de bits. A constância lógica significa que o estado do objeto, visto de fora, não mudou; a constância de bits significa que os bits do objeto na memória permanecem inalterados. A palavra-chave mutable nos permite definir a constância lógica, ou seja, mesmo que alguns dados internos do objeto mudem, o estado do objeto, em termos lógicos, não sofre alteração visível.

Por exemplo, em uma classe thread-safe, podemos usar boost::mutex para proteger o acesso aos dados. Para adquirir o bloqueio dentro de um método const, podemos declarar o mutex como mutable:

class ThreadSafeClass {
private:
    mutable std::mutex mtx_;
    int data_;
public:
    int getData() const {
        std::lock_guard<std::mutex> lock(mtx_);
        return data_;
    }
};

No exemplo acima, embora o método getData seja declarado const, precisamos do bloqueio para garantir a segurança de threads no acesso aos dados. Por isso, declaramos mtx_ como mutable, permitindo modificá-lo dentro de um método const. Nesse caso, dizemos que o estado lógico da classe não mudou; a modificação serve apenas para garantir a segurança de threads.

3. mutable em expressões Lambda

A partir do C++11, mutable também pode ser usado em expressões lambda para permitir a modificação de variáveis capturadas por valor. Por padrão, as variáveis capturadas por valor em uma lambda são imutáveis. Se for necessário modificar a variável capturada dentro da lambda, pode-se usar mutable:

int x = 0;
auto f1 = [=]() mutable { x = 42; };  // OK: 可以修改捕获的 x
auto f2 = [=]() { x = 42; };  // Error: 按值捕获的变量不能被修改

Nesse caso, mutable nos permite modificar a variável capturada dentro do corpo da função sem afetar o valor da variável externa.

4. Evitar o uso de const_cast

Sem a palavra-chave mutable, talvez precisássemos usar const_cast para tratar esses casos especiais. O const_cast remove a constância do objeto, mas tem desvantagens: ele pode eliminar completamente a proteção de constância, permitindo modificações e chamadas de métodos arbitrárias sobre o objeto, o que reduz a legibilidade e a segurança do código.

Em comparação, a palavra-chave mutable oferece um controle mais refinado. Com mutable, podemos criar "exceções" em membros de dados específicos, permitindo sua modificação em métodos const, sem remover a constância do objeto inteiro. Por isso, mutable trata esses casos especiais com mais segurança.

5. A filosofia de design do uso de mutable

A filosofia de design da palavra-chave mutable está em preservar a constância lógica da interface. Na maioria dos casos, queremos escrever código const-correct, o que significa que o estado do objeto não muda sem uma modificação explícita. mutable nos permite fazer concessões em certas implementações internas — como caches, contagem de referências, informações de depuração, etc. — sem quebrar a consistência desse design de interface.

Ao projetar uma interface, devemos deixar claro quando e por que o estado de um objeto precisa ser modificado. A palavra-chave mutable permite que o código permaneça inalterado no nível lógico e, ao mesmo tempo, oferece a capacidade de modificar membros de dados específicos. Isso exige reflexão por parte do projetista, garantindo que o uso de mutable não corrompa o conceito de constância do objeto, usando-o somente quando realmente necessário.

6.Referências

https://stackoverflow.com/questions/105014/does-the-mutable-keyword-have-any-purpose-other-than-allowing-a-data-member-to

Tópicos relacionados

Comentários