mutable关键字
🌞偶然碰见了mutable,然后学习记录一下
总结一下就是打破const成员函数不能修改成员变量的壁垒,而又想在这个函数里面使用可变的变量。
文章目录
1. mutable 的核心作用
A. 规则:const 成员函数不能修改成员变量
在 C++ 中,如果一个成员函数被声明为 const,例如:
bool empty() const { /* ... */ } // 注意这里的 const
这表示这个函数不会修改对象的任何成员变量。因此,编译器会阻止你在 const 函数中修改任何非 mutable 的成员变量。
B. mutable 的豁免权
将一个成员变量声明为 mutable,就像给它颁发了一个豁免证。它允许该变量在对象的常量成员函数中被修改。
例如 SafeQueue 代码中,mutable 是用在 empty() 函数上:
// SafeQueue.h
private:
queue<T> q;
mutable mutex m; // <--- 关键在这里
condition_variable c;
public:
// ...
bool empty(){ // 注意:这个函数没有被声明为 const!
lock_guard<mutex> lock(m);
return q.empty();
};
例子🌰
🌰下面举个例子:
假设我们要创建一个线程安全的计数器,并希望对外提供一个 const 的获取计数函数。
1. 错误的尝试 (没有 mutable)
如果我们不使用 mutable,并且尝试将 getCount() 声明为 const:
#include <mutex>
#include <iostream>
class DataTracker_Error {
private:
int data_count = 0;
std::mutex m; // ❌ 错误:不是 mutable
public:
void increment() {
std::lock_guard<std::mutex> lock(m);
data_count++;
}
// 尝试声明为 const 函数
int getCount() const {
// 🚨 编译错误!因为 lock_guard 会调用 m.lock(),
// 而 m.lock() 会改变 m 的状态,违反了 getCount() 的 const 承诺。
std::lock_guard<std::mutex> lock(m);
return data_count;
}
};
编译结果: 编译器会报错,因为它发现你在一个 const 函数中试图修改一个非 mutable 的成员变量 m。
2. 正确的实现 (使用 mutable)
为了让 const 函数 能够进行线程同步操作(即锁定互斥锁),我们必须将互斥锁声明为 mutable。
#include <mutex>
#include <iostream>
#include <thread>
class DataTracker_Correct {
private:
int data_count = 0;
mutable std::mutex m; // ✅ 正确:使用 mutable 关键字
public:
void increment() {
std::lock_guard<std::mutex> lock(m);
data_count++;
}
// getCount() 是 const 函数,但由于 m 是 mutable,所以可以锁定它。
int getCount() const {
// 逻辑上:getCount 只是读取数据,没有改变对象的数据状态。
// 物理上:它需要改变 m 的内部状态(锁定/解锁)。
std::lock_guard<std::mutex> lock(m);
return data_count;
}
};
// 示例用法
int main() {
DataTracker_Correct tracker;
// 我们可以用一个 const 引用来调用 getCount()
const DataTracker_Correct& const_tracker = tracker;
// 这行代码可以编译通过并安全执行,因为它在 const 函数中使用了 mutable 锁。
std::cout << "Current count: " << const_tracker.getCount() << std::endl;
return 0;
}
在这个例子中:
- 逻辑状态:
getCount()不改变data_count,所以它被认为是const的。 - 物理状态:
std::mutex m的内部状态(锁定/解锁)在getCount()中必须被改变。 mutable的作用:它打破了const函数不能修改成员变量的限制,允许我们在保持逻辑常量性的同时,执行线程安全所需的底层同步操作。
11万+

被折叠的 条评论
为什么被折叠?



