本文主要是介绍C++中的mutable关键字详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
目录
1.概述
2.使用场景
3.示例
4.mutable修饰Lambda表达式
5.注意事项
1.概述
在C++中,mutable
也是为了突破const
的限制而设置的。被mutable
修饰的变量,将永远处于可变的状态,即使在一个const
函数中。
我们知道,被const
关键字修饰的函数的一个重要作用就是为了能够保护类中的成员变量。即:该函数可以使用类中的所有成员变量,但是不能修改他们的值。
然而,在某些特殊情况下,我们还是需要在const
函数中修改类的某些成员变量,因为要修改的成员变量与类本身并无多少关系,即使修改了也不会对类造成多少影响。当然,你可以说,你可以去掉该函数的const关键字呀!但问题是,我只想修改某个成员变量,其余成员变量仍然希望被const保护。
2.使用场景
mutable
成员通常用于需要记录状态但又不影响对象逻辑上不可变性的场景。一个常见的例子是使用mutable
来修饰记录缓存数据的成员变量,或者是在多线程环境中记录访问次数的成员变量。
3.示例
假设我们有一个类,它代表一个可以被读取但不能被直接修改的数据库记录。但我们希望在每次访问这个记录时更新一个访问计数器,我们可以使用mutable
来实现这个需求:
#include <iostream> class DatabaseRecord {
private: int data; // 假设这是从数据库中读取的数据 mutable int accessCount; // 访问计数器,使用mutable修饰 public: DatabaseRecord(int d) : data(d), accessCount(0) {} // const成员函数,但允许修改mutable成员 void display() const { ++accessCount; // 修改mutable成员是允许的 std::cout << "Data: " << data << ", Accessed " << accessCount << " times." << std::endl; } // 假设还有其他成员函数...
}; int main() { const DatabaseRecord record(42); // 创建一个const对象 record.display(); // 调用const成员函数,同时修改mutable成员 record.display(); // 再次调用,显示访问次数增加 return 0;
}
4.mutable修饰Lambda表达式
C++11 引入了 Lambda 表达式,程序员可以凭此创建匿名函数。在 Lambda 表达式的设计中,捕获变量有几种方式;其中按值捕获(Caputre by Value)的方式不允许程序员在 Lambda 函数的函数体中修改捕获的变量。而以 mutable
修饰 Lambda 函数,则可以打破这种限制。
例如一下代码是无法编译通过的:
#include <iostream>int main()
{int x{0};auto f1 = [=]() {return ++x;}; f1();std::cout << "x =" << x << std::endl:return 0;
}
因为Lambda表达式f1,在内部修改了表达式外部x的值,但是又没有使用mutable关键字声明,此时我们只需要使用mutable关键字声明一下f1即可:
#include <iostream>int main()
{int x{0};auto f1 = [=]() mutable {return ++x;}; f1();std::cout << "x = " << x << std::endl:return 0;
}
需要注意的是,上述 f1
的函数体中,虽然我们给 x
做了赋值操作,但是这一操作仅只在函数内部生效——即,实际是给拷贝至函数内部的 x
进行赋值——而外部的 x
的值依旧是 0
。
5.注意事项
- 使用
mutable
时应当谨慎,因为它可能会隐藏类的实际不可变性,使得代码的阅读和维护变得更加困难。mutable
只能用于类的成员变量,不能用于成员函数或类型本身。- 即使在
const
成员函数中,mutable
成员也可以被修改,但这并不意味着你可以修改类的其他非mutable
成员。尝试这样做会导致编译错误。mutable
不会影响成员变量的存储方式或性能,它只是改变了编译器的检查规则。- mutable不能修饰const 和 static 类型的变量。
这篇关于C++中的mutable关键字详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!