1.定义:
在类的非静态数据成员前使用mutable,表示即使在const成员函数内,也可以修改该成员。
2.语法示例:
struct Foo {
mutable int cache; // 可在 const 成员函数中修改
int value; // 普通成员
};
3.mutable的语义
(1) 对const修饰的成员函数无效:
在普通成员函数(未加const)或非成员函数中,mutable与普通成员无异。在 const成员函数中,编译器会将this视为const Foo* const,唯有mutable成员不受该限制。
(2) 仅限非静态数据成员
只能修饰类的非静态数据成员,不能修饰静态成员、函数、类型别名等。
(3) 不影响对象的常量性
从外部看,一个const Foo依然是常量对象;mutable只是绕过了编译器对内部某些成员的写保护,不改变接口层面的const语义。
4.在C++类的定义中,为什么有的时候要在类的成员函数声明后面放上const
在C++中,把const放在成员函数声明的末尾,表明该成员函数不会修改它所属对象的任何非mutable成员,也不会调用任何非const成员函数;这样做有两个主要目的:
(1) 保证不修改对象状态
在函数后面加上const,编译器会把成员函数内部的this指针当作const MyClass* const this 来处理。你不能在这样的函数里修改任何非mutable成员变量;只能调用其他也被声明为const的成员函数。
这样一来,即使这个函数体复杂,也能编译期检查、保证它不会意外改变对象的数据成员。
struct Point {
double x, y;
// 不修改成员,安全地查询坐标
double distanceFromOrigin() const {
return std::sqrt(x*x + y*y);
}
// 如果忘了加 const,下面语句会编译报错
// Point p{3,4};
// double d = p.distanceFromOrigin(); // OK
// const Point cp{3,4};
// double d2 = cp.distanceFromOrigin(); // 必须是 const 成员函数
};
(2) 允许通过const对象或指针/引用来调用
如果你有一个const对象或通过const引用/指针访问对象,就只能调用它的const成员函数。这对设计API非常重要,因为它能区分只读操作与可变操作。
void printPoint(const Point& p) {
// 只能调用 p.distanceFromOrigin(),因为它是 const 成员函数
std::cout << p.distanceFromOrigin() << "\n";
// p.setX(5); // 错误:setX 不是 const 成员函数
}
这就是 C++ 中“const 成员函数”存在的根本原因:增强代码的可读性与安全性,帮助你在接口层面区分读操作与写操作。
1073

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



