在"The C++ programming language"一书中,作者给出了以下例子.他提到"缓存需要在可以使用之前填充".在我看来,这就是为什么放置compute_cache_value的功能.但是我不明白string_rep()的功能与它的实现有什么关系.谢谢你的澄清.
class Date{
bool cache_valid;
string cache;
void compute_cache_value( ); //fill cache
// ...
public:
// ...
string string_rep( ) const;
};
string Date:: string_rep( ) const
{
if (cache_valid == false) {
Date* th = const_cast<Date*> (this); // cast away const
th->compute_cache_value( );
th->cache_valid = true;
}
return cache;
}
Run Code Online (Sandbox Code Playgroud)
此外,作者还举例说明了以下内容:
Date d1;
const Date d2;
string s1 = d1.string_rep( );
string s2 = d2.string_rep( );
Run Code Online (Sandbox Code Playgroud)
作者表示第四个例子将显示未定义的行为.我想知道为什么.
string_rep检查是否有日期的缓存字符串表示.如果没有,它调用compute_cache_value方法来创建字符串表示并对其进行缓存,然后将缓存表示标记为有效,以便将来调用string_rep不重新计算它.
该行将const Date d2;显示未定义的行为,因为编译器可能认为它可以放入d2非易失性存储器(例如,微控制器中的闪存,或只读标记的存储器或存储器映射的存储器),并且const_cast<Date*>在这种情况下可能不起作用,导致cache_valid停留false或者cache保持空弦.
PS正如Michael J在下面指出的那样,几乎总有更好的方法来做事而不是使用const_cast.在此示例的情况下,mutable关键字派上用场.简而言之,标记类成员会mutable告诉编译器即使对象是成员,也可以更改成员const.
class Date
{
mutable bool cache_valid;
mutable string cache;
void compute_cache_value() const;
// ...
public:
// ...
string string_rep() const;
};
string Date::string_rep() const
{
if (cache_valid == false) {
compute_cache_value();
cache_valid = true;
}
return cache;
}
Run Code Online (Sandbox Code Playgroud)
...虽然我认为它是compute_cache_value有责任设置cache_valid,我会考虑加入operator string() const { return string_rep(); }到Date.
最后一件事情mutable是,编译器更好地了解发生了什么,并且在类似情况下d2,可以将对象放在易失性存储器中,尽管它声明为const.