《C++程序设计原理与实践(PPP)》Month类重载>>运算符读取疑问
问题核心:
Month的operator>>没有清空历史数据 你的误解本质是忽略了operator>>对Month成员的处理范围:它只会修改本次读取涉及的成员,不会清空Month对象里已有的历史读数,这就是数据残留/累加的根源。
我们一步步拆解逻辑:
Month的默认初始化规则
新创建的Month对象默认状态是:
month成员值为not_a_monthday成员是包含32个Day对象的数组,每个Day的hour数组的24个元素全部初始化为not_a_reading
operator>> (istream&, Month&)的实际行为
你可以逐行看它的实现,它对传入的Month& m只做两类修改:
- 把
m.month更新为本次读取到的月份值 - 对本次读取到的每一个合法
Reading,只修改m.day[r.day].hour[r.hour]对应的温度值
它完全没有对m.day数组做全局清空操作,所有本次没读到的day、hour位置,都会保留之前的值。
- 循环复用同一个
Month对象的问题复现
我们举个实际的运行场景就一目了然:
假设我们用你认为没问题的for循环写法:
for (Month m; is >> m; ) y.month[m.month] = m;
- 第一次循环:
m是全新初始化的对象,读取1月数据,假设读到两个读数(1 0 10)、(2 0 12),那么m.day[1].hour[0] = 10、m.day[2].hour[0] = 12,其余位置都是not_a_reading,赋值给y.month[1],结果正确。 - 第二次循环:复用同一个
m对象,读取2月数据,假设本次只读到一个读数(1 0 8)。此时operator>>只会把m.month改成2,把m.day[1].hour[0]改成8,但是m.day[2].hour[0]还保留着上次的12。赋值给y.month[2]后,2月的数据里就平白多了一个不属于它的1月2号0点的12度读数,也就是书中说的「每个新月份都会包含当年所有之前月份的读数」的问题。
而把Month m放在循环内部的写法,每次循环都会创建一个全新的、所有读数位置都是not_a_reading的空白Month对象,自然不会有历史数据残留的问题。
内容的提问来源于stack exchange,提问作者jackriffold15
相关产品推荐
相关产品推荐

