为STL结构的CityReport类实现自定义嵌套迭代器遇阻
实现CityReport嵌套迭代器的解决方案
你的核心问题是要实现嵌套迭代——既要遍历外层的std::list<std::shared_ptr<ReportsBin>>,又要遍历每个ReportsBin内部的MemberReport集合。因为list不支持下标访问,所以必须用迭代器跟踪当前位置,而非指针或下标。
Iter类需要维护的状态
你需要在Iter里存两个迭代器:
- 外层迭代器:
std::list<std::shared_ptr<ReportsBin>>::iterator,用来跟踪当前遍历到哪个ReportsBin - 内层迭代器:假设
ReportsBin里的成员报告存在类似std::list<std::shared_ptr<MemberReport>>的容器中,对应容器的迭代器,用来跟踪当前ReportsBin里的具体报告
另外还要存一个指向CityReport的指针,用来获取外层list的end(),判断迭代是否结束。
核心方法实现示例
假设ReportsBin有公开成员mMemberReports(类型为std::list<std::shared_ptr<MemberReport>>),代码实现如下:
class Iter { private: CityReport* mCityReport; std::list<std::shared_ptr<ReportsBin>>::iterator mOuterIt; std::list<std::shared_ptr<MemberReport>>::iterator mInnerIt; // 辅助函数:找到下一个包含非空成员报告的ReportsBin void moveToNextValid() { while (mOuterIt != mCityReport->mReportBins.end()) { auto& bin = *mOuterIt; if (!bin->mMemberReports.empty()) { mInnerIt = bin->mMemberReports.begin(); return; } ++mOuterIt; } // 所有Bin遍历完毕,将内层迭代器置为无效状态 static std::list<std::shared_ptr<MemberReport>> emptyList; mInnerIt = emptyList.end(); } public: // 从CityReport初始化迭代器 explicit Iter(CityReport* cityReport) : mCityReport(cityReport) { mOuterIt = mCityReport->mReportBins.begin(); moveToNextValid(); } // 构造结束迭代器 Iter(CityReport* cityReport, bool isEnd) : mCityReport(cityReport) { mOuterIt = mCityReport->mReportBins.end(); static std::list<std::shared_ptr<MemberReport>> emptyList; mInnerIt = emptyList.end(); } // operator*:返回当前指向的MemberReport智能指针 std::shared_ptr<MemberReport> operator*() const { return *mInnerIt; } // 前缀递增运算符 Iter& operator++() { ++mInnerIt; // 当前Bin的报告遍历完后,切换到下一个有效Bin if (mInnerIt == (*mOuterIt)->mMemberReports.end()) { ++mOuterIt; moveToNextValid(); } return *this; } // 后缀递增运算符(可选实现) Iter operator++(int) { Iter temp = *this; ++(*this); return temp; } // 相等判断 bool operator==(const Iter& other) const { // 外层迭代器均到达末尾时,视为相等 if (mOuterIt == mCityReport->mReportBins.end() && other.mOuterIt == other.mCityReport->mReportBins.end()) { return true; } // 否则需要内外层迭代器都匹配 return mOuterIt == other.mOuterIt && mInnerIt == other.mInnerIt; } bool operator!=(const Iter& other) const { return !(*this == other); } };
关键注意点
- 如果
ReportsBin内部的报告容器不是std::list,只需将内层迭代器换成对应容器的迭代器即可(比如std::vector::iterator) - 必须处理空的ReportsBin:
moveToNextValid函数会跳过所有无成员报告的Bin,避免迭代到无效内容 - 结束迭代器的标记:以外层迭代器到达
mReportBins.end()作为迭代结束的标志 - 确保
CityReport的mReportBins是公开可访问的——如果不是,你需要确认是否有合法的方式获取其迭代器(比如CityReport提供begin()/end()方法),但你提到不能修改CityReport,这里默认它是公开可访问的
之前方案的问题
- 用
ReportsBin*作为构造参数:只能遍历单个ReportsBin的内容,无法处理外层list的嵌套结构,自然无法实现完整迭代 - 用
CityReport*但不用迭代器:list不支持下标访问,必须用迭代器跟踪位置,这是list容器的特性决定的
内容的提问来源于stack exchange,提问作者notimportant
相关产品推荐
相关产品推荐

