在C++中mutable是什么

一般类中的mutable

假如一个类的某个成员函数被是const修饰,那么这个类的隐藏对象参数将会被添加const限定符(见在C++中this是什么),此时我们将无法修改任何成员,除非通过const_cast

加入我们需要在这类函数被调用时修改某个成员变量(可能是用于统计),将会十分困难。

此时可以在需要被修改的成员变量前添加mutable限定符使其可以被修改,但是这个成员变量不可以是引用类型,不可以拥有顶层的const限定符,也不可以是静态成员。

lambda中的mutable

在lambda中,被捕获的变量无法修改,如果在lambda的小括号后面添加mutable,那么这些变量将可以被修改。

不应该假设被捕获变量的类型的限定符,御三家对被捕获的变量的类型有着不同的看法,看下面的例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class M {
mutable int i = 0;
public:
bool operator()() const {
return std::is_same_v<decltype(i), const int>;
}
};

class T {
int i = 0;
public:
bool operator()() const {
return std::is_same_v<decltype(i), const int>;
}
};

class C {
const int i = 0;
public:
bool operator()() const {
return std::is_same_v<decltype(i), const int>;
}
};

int main() {
// gcc 11.2
// clang 14.0.0
// msvc v19.31
auto check_const = [i = 0] () { return std::is_same_v<decltype(i), const int>; };
auto check_mutable = [i = 0] () mutable { return std::is_same_v<decltype(i), const int>; };
cout << check_const(); // 1 0 0
cout << check_mutable(); // 0 0 0
cout << M()(); // 0 0 0
cout << T()(); // 0 0 0
cout << C()(); // 1 1 1
}

可以有如下的推测。

gcc在被捕获的变量上添加const,在添加mutable后移除;

而clang和msvc则在成员函数的隐藏对象形参上添加const,在添加mutable后在所有的成员上添加mutable或移除隐藏对象形参上的const

文章目录
  1. 1. 一般类中的mutable
  2. 2. lambda中的mutable
|