mutable 关键字教程

在 C++ 中,mutable 是一个用于修饰类成员变量的关键字,其核心作用是允许在 const 成员函数中修改被修饰的成员变量,打破了“const 成员函数不能修改类成员”的默认规则,同时不影响其他场景下成员变量的访问和修改权限。

一、核心用途:突破 const 成员函数的限制

默认情况下,const 成员函数的设计目的是“不修改类的成员变量”(保证对象状态不变),编译器会禁止在其中修改普通成员变量。但实际开发中,部分成员变量(如“缓存数据”“计数器”)的修改不会影响对象的核心逻辑,此时可通过 mutable 修饰这类变量,允许在 const 成员函数中修改它们。

示例:const 成员函数中修改 mutable 变量

#include <iostream>
#include <string>
using namespace std;

class Student {
private:
    string name;          // 普通成员变量(const 函数中不可修改)
    mutable int queryCnt; // mutable 成员变量(const 函数中可修改)
public:
    // 构造函数初始化
    Student(string n) : name(n), queryCnt(0) {}

    // const 成员函数:查询姓名(不修改核心状态,但需统计查询次数)
    string getName() const {
        queryCnt++; // 允许修改 mutable 变量
        return name;
    }

    // 普通成员函数:获取查询次数
    int getQueryCnt() const {
        return queryCnt;
    }
};

int main() {
    const Student s("张三"); // 定义 const 对象(只能调用 const 成员函数)
    cout << s.getName() << endl; // 调用 const 函数,queryCnt 自增为 1
    cout << s.getName() << endl; // 再次调用,queryCnt 自增为 2
    cout << "查询次数:" << s.getQueryCnt() << endl; // 输出:2
    return 0;
}

输出结果

张三
张三
查询次数:2

二、使用场景:哪些情况需要 mutable?

mutable 的使用需遵循“最小影响原则”,仅用于修饰“修改不影响对象核心逻辑”的成员变量,常见场景包括:

  1. 统计类:如“函数调用次数”“数据访问次数”(如上例的 queryCnt);
  2. 缓存数据:如对象中缓存的计算结果(例如“计算一次后存储,后续直接返回”,缓存的更新不影响对象核心状态);
  3. 线程同步变量:如 mutex(互斥锁),在 const 函数中加锁/解锁不会影响对象核心逻辑。

三、注意事项:避免滥用 mutable

  1. 仅修饰类成员变量mutable 不能修饰普通变量、全局变量、函数参数,也不能修饰 static 成员变量(static 属于类,不属于单个对象,const 函数对其无限制);

    // 错误用法示例
    mutable int num; // 错误:不能修饰普通全局变量
    void func(mutable int x) {} // 错误:不能修饰函数参数
    
  2. 不改变对象核心逻辑mutable 的本质是“允许修改非核心状态”,若修饰核心成员变量(如示例中的 name),会违背 const 函数的设计初衷,导致代码逻辑混乱;

  3. 与 const 的配合mutable 仅作用于 const 成员函数,在普通成员函数中,mutable 变量的访问和修改与普通变量无区别。

四、对比:mutable 与 const 的关系

场景 普通成员变量 mutable 成员变量
普通成员函数中 可修改 可修改
const 成员函数中 不可修改(编译报错)
const 对象中 不可修改 可修改(通过 const 函数)

五、总结

  • mutable 是 C++ 为“const 成员函数中修改非核心变量”提供的解决方案;
  • 核心作用:允许 const 成员函数修改被修饰的成员变量,不影响对象核心逻辑;
  • 关键原则:不滥用,仅修饰“修改无副作用”的成员变量(如计数器、缓存)。

0 条评论

目前还没有评论...