C++
 Computer >> コンピューター >  >> プログラミング >> C++

C++のmutableキーワードとは?constオブジェクトでも値を変更できる仕組みを解説

mutableキーワードとは

C++におけるmutable(ミュータブル)キーワードを付けたデータメンバーは、オブジェクトがconst型で宣言されていても、実行時に値を変更することができます。これは、変更を一切許さない「定数(const)」とは正反対の性質を持つ指定子です。

実際のプログラミングでは、「ほとんどのデータメンバーは定数として保護したいが、1つか2つのメンバーだけは変数として更新したい」というケースがよくあります。例えば、キャッシュ値やアクセス回数のカウンタなどが該当します。このような場面でmutableは、クラスの設計とデータ管理を柔軟に行うための非常に有用な概念となります。

コード例

以下のサンプルでは、constオブジェクトの中で、通常のメンバーとmutableメンバーの挙動の違いを確認できます。

#include <iostream>
using namespace std;

class Test {
    public:
        int a;            // 通常のメンバー(constオブジェクトでは変更不可)
        mutable int b;    // mutableメンバー(constオブジェクトでも変更可能)

    Test(int x = 0, int y = 0) {
        a = x;
        b = y;
    }

    void seta(int x = 0) {
        a = x;
    }

    void setb(int y = 0) {
        b = y;
    }

    void disp() {
        cout << endl << "a: " << a << " b: " << b << endl;
    }
};

int main() {
    const Test t(10, 20);   // constオブジェクトとして生成

    cout << t.a << " " << t.b << "\n";

    // t.a = 30;  // ← コンパイルエラー:オブジェクトがconstのためaは変更できない
    t.b = 100;    // ← 問題なし:bはmutableなので変更できる

    cout << t.a << " " << t.b << "\n";

    return 0;
}

実行結果

10 20
10 100

動作のポイント

  • t.a = 30; のコメント行を有効にするとコンパイルエラーになります。オブジェクトt自体がconstであるため、通常のメンバーaの書き換えは許されません。
  • 一方、t.b = 100; は問題なく実行されます。bにはmutableが付いているため、constオブジェクト内でも値の変更が可能だからです。

mutableの主な活用シーン

  • キャッシュの保持: 高コストな計算結果をconstメンバ関数内でキャッシュし、次回以降の処理を高速化する。
  • ミューテックスの保持: constメンバ関数内でもスレッド安全性を確保するために、内部でmutexをロック・アンロックする。
  • 論理的には不変なオブジェクトの内部状態管理: 外部から見た振る舞いは変わらないまま、内部的な統計情報やフラグだけを更新する。

このようにmutableは「オブジェクト全体の不変性を保ちながら、一部の内部状態だけを変更したい」という設計要件を実現するための重要なキーワードです。

  1. C++でプロセスを強制終了する方法:BFSを使った実装解説

    n個のプロセスがあると仮定します。各プロセスには、PID(プロセスID)と呼ばれる一意の識別子が割り当てられており、さらにPPID(親プロセスID)も持っています。各プロセスが持てる親プロセスは1つだけですが、子プロセスは1つでも複数でも構いません。これはまさに木構造と同じ形です。PPIDが0になるプロセスは1つだけであり、それはそのプロセスに親が存在しないことを意味します。また、すべてのPIDは一意な正の整数です。問題の概要ここでは、2つの整数リストを使ってプロセスの一覧を表現します。1つ目のリストには各プロセスのPIDが含まれ、2つ目のリストにはそれに対応するPPIDが含まれます。このとき

  2. C++で解くリスのナッツ収集シミュレーション ― 最小移動距離を求めるアルゴリズム

    問題概要 1本の木、1匹のリス、そして複数のナッツがフィールド上にあります。それぞれの位置は2次元グリッドのセルで表現されます。この問題の目的は、リスがすべてのナッツを集めて木の下に1個ずつ運ぶときの最小移動距離を求めることです。 リスの行動には次の制約があります。 一度に持てるナッツは最大1個 移動は上下左右の4方向で、隣接するセルへのみ可能 距離は移動回数(ステップ数)で表される たとえば、入力が「高さ: 5 / 幅: 7 / 木の位置: [2,2] / リスの位置: [4,4] / ナッツ: [[3,0], [2,5]]」の場合、出力は 12 となります。 解法のポイント まず、