在C++中,mutable是为了突破const的限制而设置的。
被mutable修饰的变量,将永远处于可变的状态,即使在一个const函数中,甚至结构体变量或者类对象为const,其mutable成员也可以被修改。
例如:
#include <iostream>
class Tester
{
public:
Tester(int x, int y) : a_normal(x),b_mutable(y)
{}
void printAll() const
{
std::cout << "a_normal=" << a_normal << "; b_mutable=" << b_mutable << std::endl;
}
int a_normal;
mutable int b_mutable;
};
int main()
{
const Tester tst(2,3);
tst.a_normal = 22;
tst.b_mutable = 33;
tst.printAll();
return 0;
}
编译报错,报错信息如下
test4mutable.cpp: In function ‘int main()’ :test4mutable.cpp:20: error: assignment of data-member ‘Tester::a_normal’ in read-only structure
我们将报错的那行代码注释掉后重新编译,通过运行。
mutable在类中只能修饰非静态数据成员。
const修饰的变量在任何情况下它的值都不会被改变。
const修饰的函数不能直接或间接地改变任何函数体以外的变量的值,即使调用一个可能造成这种改变的函数也不行。
关于const关键字的详细解析请参考博文:const关键字浅析
mutable修饰的变量将永远处于可变的状态,即使在一个const函数中。
所以mutable和const形成了一个对称的定义:一个永远不变,一个永远可变。
那么有3个问题需要考虑:
保护类的成员变量不在成员函数中被修改,是为了保证模型的逻辑正确,通过用const关键字来避免在函数中错误的修改了类对象的状态。并且在所有使用该成员函数的地方都可以更准确的预测到使用该成员函数的带来的影响。
而mutable则是为了能突破const的封锁线,让类的一些次要的或者是辅助性的成员变量随时可以被更改。
没有使用const和mutable关键字当然没有错,const和mutable关键字只是给了建模工具更多的设计约束和设计灵活性,而且程序员也可以把更多的逻辑检查问题交给编译器和建模工具去做,从而减轻程序员的负担。
如果类的成员函数不会改变对象的状态,那么这个成员函数一般会声明成const的。但是,如果希望在const函数中修改一些和类状态无关的数据成员,那么可以使用mutable修饰这个成员。
明智地使用mutable关键字,可以向用户隐藏实现细节,而无需使用不确定的东西,提高代码质量。
例如:
#include <iostream>
class Tester
{
public:
Tester(int x, int y) : a_normal(x),b_mutable(y), printCount(0)
{}
void printAll() const
{
std::cout << "a_normal=" << a_normal << "; b_mutable=" << b_mutable << std::endl;
std::cout << "print " << ++printCount<< " times" << std::endl << std::endl;
}
int a_normal;
mutable int b_mutable;
mutable int printCount;
};
int main()
{
const Tester tst(2,3);
tst.b_mutable = 33;
tst.printAll();
tst.printAll();
tst.printAll();
return 0;
}
在上例中,printAll函数是一个const函数,但是希望在打印的同时,记录打印次数,因此,在类中增加了一个成员变量printCount,该成员变量和类本身的状态无关,并且需要在printAll函数中改变,因此使用mutable关键字修饰,实现了统计打印次数的目的。
执行结果如下图所示:
原文地址:http://blog.csdn.net/zs634134578/article/details/45665947