如何在不欺骗编译器的情况下保持这个常量正确?
Posted
技术标签:
【中文标题】如何在不欺骗编译器的情况下保持这个常量正确?【英文标题】:How to keep this const-correct without cheating the compiler? 【发布时间】:2011-12-17 13:57:26 【问题描述】:我有一个这样的 C++ 类:
class Example
public:
int getSomeProperty(int id) const;
private:
lazilyLoadSomeData();
基本上getSomeProperty()
返回一些已经使用lazilyLoadSomeData()
加载的数据。由于我不想在需要之前加载这些数据,所以我在 getSomeProperty()
中调用此方法
int Example::getSomeProperty(int id) const
lazilyLoadSomeData(); // Now the data is loaded
return loadedData[id];
这不起作用,因为 lazilyLoadSomeData() 不是 const。即使它只更改可变数据成员,编译器也不会允许它。我能想到的唯一两个解决方案是:
在类构造函数中加载数据,但我不想这样做,因为延迟加载所有内容会使应用程序更快。
将lazilyLoadSomeData()
设为常量。它会起作用,因为它只更改可变成员,但它似乎并不正确,因为从名称来看,该方法显然正在加载某些内容并且显然正在进行一些更改。
关于什么是处理这个问题的正确方法有什么建议,而不必欺骗编译器(或完全放弃 const 正确性)?
【问题讨论】:
¤ 这就是mutable
关键字的用途。更倾向于“作弊”方向的另一种选择是保留指向数据的指针。我提到这一点是为了明确识别反模式并避免它;对惰性数据使用mutable
。干杯&hth.,
【参考方案1】:
您可以创建一个您声明mutable
并封装延迟加载策略的代理成员对象。该代理本身可以从您的 const
函数中使用。作为奖励,您最终可能会得到一些可重用的代码。
【讨论】:
除了...从语义上讲,您只是做完全相同的事情,因此有人可能会说这是同一个问题。老实说,问题是“愚蠢”是某种方式,因为mutable
是关于作弊,以一种受控的方式。【参考方案2】:
我会将调用转发到一个代理对象,它是此类的 mutable
成员,如下所示:
class Example
public:
int getSomeProperty(int id) const
m_proxy.LazyLoad();
return m_proxy.getProperty(id);
private:
struct LazilyLoadableData
int GetProperty(int id) const;
void LazyLoad();
;
mutable LazilyLoadableData m_proxy;
;
【讨论】:
当您不使用“pImpl”时确实如此。但如果你这样做,就不需要可变的。您可以只修改 pImpl 指向的内容,因为只有 pImpl 本身是 const..【参考方案3】:将 lazilyLoadSomeData() 设为常量。它会起作用,因为它只更改可变成员,但它似乎并不正确,因为从名称来看,该方法显然正在加载某些内容并且显然正在进行一些更改。
不,它没有做出一些改变,至少从调用 getSomeProperty 的人的角度来看是这样。如果你做对了,所有的变化都是纯粹的内部变化,从外部看不到。这是我会选择的解决方案。
【讨论】:
以上是关于如何在不欺骗编译器的情况下保持这个常量正确?的主要内容,如果未能解决你的问题,请参考以下文章
在不丢失 .data 常量的情况下混合汇编和 C 的正确标志是啥
如何在不使用模拟位置的情况下在 android 上欺骗位置?