"可变"变量只能由 const 方法之一可变?

'mutable' variable mutable only by one of the const methods?

本文关键字:方法 const 可变 变量      更新时间:2023-10-16

今天我已经了解了C++中的mutable关键字,并希望在我的代码中使用它。

我有一个包含许多const方法的类,其中一个应该能够修改对象的一些变量(保留对象的逻辑状态)。但是,我不想让所有const方法修改变量,只修改选定的方法。有什么办法可以做到这一点吗?也许有const_cast

(我所说的代码是联合查找结构的实现。Find操作不会更改结构的逻辑状态(它只搜索树的根),而是通过执行所谓的路径压缩来更改物理状态)

谢谢!

编辑:我从我所指的代码中添加了一段摘录:

class UnionFind {
public:
void Union(int a, int b) {...}
int Find(int x) const {
// logically, this method is const
while(x != parents[x]) {
// path compression
// the next three lines modify parents and sizes, 
// but the logical state of the object is not changed
sizes[parents[x]] -= sizes[x];
sizes[parents[parents[x]]] += sizes[x];
parents[x] = parents[parents[x]];
x = parents[x];
}
return x;
}
int someOtherMethodThatAccessesParents() const {
// this method does access parents, but read only.
// I would prefer if parents behaved like if it was 
// not 'mutable' inside this method
...
}
private:
// these have to be mutable if I want the Find method
// to be marked const (as it should be)
// but making them mutable then does not enforce 
// the physical non-mutability in other const methods :(
mutable std::vector<int> parents;
mutable std::vector<int> sizes;
};

乍一看,除非您使用讨厌的const_cast,否则无法实现这一点。但不要这样做,因为在最初声明为 const 的const_cast之后尝试修改变量的行为是未定义的。

但是,使用友谊来实现您想要的东西可能是可行的,因为这可以在逐个功能的基础上进行控制,而可变性,正如您正确指出的那样,不能。

将要修改的变量放在基类中,并将其标记为私有。也许为该成员提供一个"getter"函数。该函数将是 const,并且可能会返回对成员的 const 引用。然后使函数成为该基类的好友。该函数将能够更改该私有成员的值。

如果你能负担得起使用mutable,这是正确的方法。

尽管如此,还是可以做到你所要求的。通常这是通过"假this"成语来完成的:

MyClass *mutableThis = const_cast<MyClass*>(this);

然后通过新指针正常访问您的字段。如果您必须支持一些没有mutable支持的旧编译器,这也是这样做的方法。

但请注意,这通常是一种危险的做法,因为它很容易将您带入未定义行为的可怕领域。如果原始对象实际上被声明const(而不是仅通过const指针/引用进行访问),那么您就是在自找麻烦。

简而言之:尽可能使用mutable,在不能使用时使用假this,但前提是你知道自己在做什么。