mutable

mutable

想象一下,你有一个成员函数,它被标记为const,因为你不希望在该函数中修改成员变量,为了保证类状态不变。

但是后来随着版本演进,你又不得不在该函数中修改一个新的成员变量,这个新的成员变量通常和类状态无关。

那么你需要认识下mutable。

mutable

mutable基本都用在两种使用场景,这个在该地址有提到。

  • const场景
  • lambda表达式场景

const场景

我们前面提到场景就是属于第一类场景。

注意,被const修饰并不代表一定不能改变,它只是表示开发人员承诺不去改变它。

在被const修饰的方法中,使用mutable可以突破const的限制。

C++ supports two notions of immutability:

  • const: meaning roughly ‘‘I promise not to change this value.’’ This is used primarily to specify interfaces so that data can be passed to functions using pointers and references without fear of it being modified. The compiler enforces the promise made by const. The value of a const can be calculated at run time.

  • constexpr: meaning roughly ‘‘to be evaluated at compile time.’’ This is used primarily to specify constants, to allow placement of data in read-only memory (where it is unlikely to be corrupted), and for performance. The value of a constexpr must be calculated by the compiler.

​ ——《A_Tour_of_C++》by Bjarne Stroustrup

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
/*
* Copyright (C) 2023 hangliebe.com
*/
#include <iostream>

class Entity
{
private:
int age = 5;
mutable int count = 0; // 记录getAge被执行了多少次

public:
const int getAge() const
{
count++; // 如果不加mutable修饰,这里是会编译报错的
return age;
}
};

int main()
{
const Entity entity;
entity.getAge();
}

lambda表达式场景

观察下面这段代码,lambda表达式中以引用的方式传入了num入参,因此在表达式改变num的值会引起num改变。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/*
* Copyright (C) 2023 hangliebe.com
*/
#include <iostream>

int main()
{
int num = 5;
auto fun = [&num]() {
num++;
std::cout << num << std::endl; // 打印6
};
fun();
std::cout << num << std::endl; // 打印6
}

为了不改变num的值,用by value的方式入参。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/*
* Copyright (C) 2023 hangliebe.com
*/
#include <iostream>

int main()
{
int num = 5;
auto fun = [=]() {
num++; // 编译失败 increment of read-only variable ‘num’
std::cout << num << std::endl;
};
fun();
std::cout << num << std::endl;
}

上面这段代码会编译失败,因为c++默认情况下,在lambda表达式中,如果以by value方式入参的变量,默认是const, 是不允许修改的。

这时候,使用mutable可以解决这个问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/*
* Copyright (C) 2023 hangliebe.com
*/
#include <iostream>

int main()
{
int num = 5;
auto fun = [=]() mutable {
num++;
std::cout << num << std::endl; // 打印6
};
fun();
std::cout << num << std::endl; // 打印5
}

上面讲述了mutable常见的用法,注意,mutable不能修饰静态的以及常量。

1
2
mutable static int num = 4; // conflicting specifiers in declaration of ‘num’
mutable const int num = 4; // error: ‘const’ ‘num’ cannot be declared ‘mutable’


关注博客或微信搜索公众号多媒体与图形,获取更多内容,欢迎在公众号留言交流!
扫一扫关注公众号
作者

占航

发布于

2023-03-05

更新于

2023-10-04

许可协议

评论