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は「オブジェクト全体の不変性を保ちながら、一部の内部状態だけを変更したい」という設計要件を実現するための重要なキーワードです。
-
C++でプロセスを強制終了する方法:BFSを使った実装解説
n個のプロセスがあると仮定します。各プロセスには、PID(プロセスID)と呼ばれる一意の識別子が割り当てられており、さらにPPID(親プロセスID)も持っています。各プロセスが持てる親プロセスは1つだけですが、子プロセスは1つでも複数でも構いません。これはまさに木構造と同じ形です。PPIDが0になるプロセスは1つだけであり、それはそのプロセスに親が存在しないことを意味します。また、すべてのPIDは一意な正の整数です。問題の概要ここでは、2つの整数リストを使ってプロセスの一覧を表現します。1つ目のリストには各プロセスのPIDが含まれ、2つ目のリストにはそれに対応するPPIDが含まれます。このとき
-
C++で解くリスのナッツ収集シミュレーション ― 最小移動距離を求めるアルゴリズム
問題概要 1本の木、1匹のリス、そして複数のナッツがフィールド上にあります。それぞれの位置は2次元グリッドのセルで表現されます。この問題の目的は、リスがすべてのナッツを集めて木の下に1個ずつ運ぶときの最小移動距離を求めることです。 リスの行動には次の制約があります。 一度に持てるナッツは最大1個 移動は上下左右の4方向で、隣接するセルへのみ可能 距離は移動回数(ステップ数)で表される たとえば、入力が「高さ: 5 / 幅: 7 / 木の位置: [2,2] / リスの位置: [4,4] / ナッツ: [[3,0], [2,5]]」の場合、出力は 12 となります。 解法のポイント まず、