首页 > 解决方案 > `const_cast 可以接受吗(this)` 如果公共状态没有改变?

问题描述

我有一个 C++ 类,可以随时随地计算一些统计参数。this如果我不更改公开可见的状态,并且const所讨论的函数是幂等且纯/引用透明的,那么抛弃 const 以实现冗长计算的缓存是否可以接受?

#include <cstdio>
#include <unistd.h>

class Compute {
public:
    Compute() = default;
    ~Compute() = default;

    void add(int x) {
        sum += x;
        squareDirty = true;
    }

    int getSquare() const {
        if (squareDirty) {
            auto &mthis = *const_cast<Compute*>(this);
            usleep(2000); // takes a long time!
            mthis.squareCached = sum * sum;
            mthis.squareDirty = false;
        }

        return squareCached;
    }

private:
    int sum = 0;
    bool squareDirty = false;
    int squareCached;
};

void foo() {
    Compute c{};
    c.add(10);
    c.add(20);
    printf("%d\n", c.getSquare()); // long time...
    printf("%d\n", c.getSquare()); // fast!
}

我只想在实际需要时才懒惰地计算它们——并缓存它们直到新数据到达。

然而,缓存东西意味着我的T getSquare() const方法必须抛弃constthis改变私有状态。

但是getSquare实际上是幂等的,编译器可以计算一次并存储为常量,或内联,或做任何其他事情,因为我的私有状态是可丢弃的。

这是可以接受的事情,还是我要求 UB?

标签: c++constantsc++20

解决方案


const_cast<Foo*>(this)如果公共状态不改变可以接受吗?

修改 const 对象的非可变状态是未定义的行为。

出于这个原因,除非可以证明所引用的对象是非常量的,否则在 const 转换之后通过对 const 的引用来修改非可变状态是不可接受的。

该状态是否公开无关紧要。我认为这种类型的透明缓存是可变成员存在的原因。


推荐阅读