在C ++编程语言第4版第16.2.9.4节“间接可变性”中有一个使用间接而不是mutable
关键字进行延迟评估的示例草图。
struct cache {
bool valid;
string rep;
};
class Date {
public:
// ...
string string_rep() const;
private:
cache * c; // initialize in constructor
void compute_cache_value() const;
// ...
};
string Date::string_rep() const {
if (!c->valid) {
compute_cache_value();
c->valid = true;
}
return c->rep;
}
没有太多解释:
当只允许小对象的一小部分表示允许更改时,声明成员
mutable
是最合适的。通过将更改的数据放在单独的对象中并直接访问它,可以更好地处理更复杂的情况。
我正在寻找更完整的解释。特别是,
c
是否会失败(在一个非常重要的程度上)懒惰?也就是说,它确实可以为你做多少不需要的工作。c
是指针而不是unique_ptr
?前面的章节为了证明异常安全性和RAII而付出了一些努力。mutable cache c
,为什么不只有一个c
成员呢?换句话说,这是一个真实的模式还是一个人为的例子来展示间接与持久性?
答案 0 :(得分:4)
“小小约束”不是一个真正的约束,只是提示如何编写代码(它与使用过的内存没什么关系)。如果你有一个有30个成员的类,其中20个是可变的,那么将它分成两个类(一个用于可变部分,一个用于其余部分)可能更有意义。
为什么它不是一个聪明的指针:不知道,但可能是一本太累的书作者:p
为什么它是一个指针:你是对的,没有必要。制作一个没有任何指针的可变缓存对象也会起作用,如果不需要任何类似指针的方式(比如从外部获取现有对象),指针只会增加另一种制作错误的可能性。
答案 1 :(得分:1)
警告:以下文字对战场程序员都没有任何实际价值,而不是程序员 - 哲学家或普通哲学家。另外,我是Bjarne Stroustrup的忠实粉丝,我的观点可能有偏见。不幸的是,StackOverflow格式不适合书籍讨论。功能
另外,我们正在讨论关于constness-mutability的尴尬问题,我们应该对编译器和类用户撒谎。而且没有单一的正确意见。我准备被评论和投票;)
简而言之:
长期:
小小约束是什么?它是少量的内存还是一个 少量的逻辑?
我再次引用Bjarne:
当只允许小型对象的表示的一小部分时,声明成员可变最合适
我认为他的意思是"少数数据成员"这里。通过将数据成员分组到单独的类中进行重构通常是一个很好的建议。 "适当"之间的比例是多少?和"小"?你自己决定(给出一个真正的问题,一个分析器工具和内存/速度/ battery_life / money / client_happiness等约束。)
没有在构造函数中初始化c失败(到一个非常重要的程度)懒惰?也就是说,它确实可以帮助你做很多事情。
好吧,通过延迟初始化,我们指的是每次用户请求字符串时非计算正确的字符串值(即compute_cache_value()
),但仅在真正需要时。不是用空字符串初始化,对吧? (std::string
无论如何都在构造时初始化为空字符串)
第16.2.9.3和16.2.9.4章中Bjarne的代码中没有任何构造函数!并且您也不会在代码中的构造函数中计算字符串,而是使用空字符串文字初始化它。所有计算都推迟到最后一刻。所以,懒惰的初始化对我来说非常适合。
进一步过早优化,如果你想要真正的延迟初始化,你可能会在构造函数中保留cache*
指针未初始化,并分配on第一次Date::string_rep()
来电。如果您的缓存很大并且用户从不需要它,那么这将是安全的堆。这样你就可以在cache
构造函数中包装计算,这使得懒惰的评估变为非常懒惰的初始化
为什么c是裸指针而不是unique_ptr?该 前几章为了证明异常而付出了一些努力 安全和RAII。
In" C ++编程语言,第4版"第17章介绍了智能指针,我们讨论的是第16章。此外,描述可变性并不重要,只要你在析构函数中设法delete
就没有任何优势。另一件事是作者本章将解释为什么你可以改变smart_ptr cache
所拥有的资源,smart_ptr
方法中只有常量const
对象,这将引入描述运算符重载(大多数高级 Java和Python 程序员会在那个地方丢掉这本书;)。
除此之外,这一般是一个难题。首先,Bjarne Stroustrup的书籍主要被视为教材或指南。那么,在教新手时,我们应该先进入智能指针还是先教导原始指针?我们应该立即使用标准库还是将其留给最后几章? C ++ 14从一开始就是" C +"第一?谁知道?还有一个问题被称为"过度使用智能指针",尤其是shared_ptr
。
如果你打算在构造函数中分配和初始化c,为什么不只有一个可变的缓存c成员呢?
那是16.2.9.3中描述的内容,对吧?
在这里添加一个间接级别是替代解决方案(显示"没有适用于所有目的的通用解决方案")并演示这个惊人的引用:
<击>
计算机科学中的所有问题都可以通过另一层次的间接解决,除了间接层太多的问题。 - David J. Wheeler 击>
没有。当用户 xan 澄清时,16.9.3是关于多个可变成员,而单个mutable
struct
会提供一些关注点分离。
希望你喜欢阅读!