C++为自定义List类实现范围式for循环的技术问询
实现List类的范围式for循环支持
我来帮你搞定这个范围for的问题!你当前写的begin()直接返回了第一个元素的引用,这其实不符合范围for循环的底层要求——范围for需要迭代器对象,而不是直接的元素引用。它的工作逻辑是:调用容器的begin()和end()拿到迭代器,然后通过++移动迭代器、*获取元素,直到迭代器等于end()为止。
下面给你两种可行的实现方式,按需选择:
方法一:自定义迭代器(灵活可控)
自己写一个迭代器类,包装vector的迭代器,让它解引用后直接返回Object&,而不是shared_ptr<Object>。这种方式适合你需要对迭代器行为做更多定制的场景。
#include <vector> #include <memory> class Object {}; class List { public: std::vector<std::shared_ptr<Object>> list; // 非const版本迭代器 class iterator { private: std::vector<std::shared_ptr<Object>>::iterator it; public: explicit iterator(std::vector<std::shared_ptr<Object>>::iterator iter) : it(iter) {} // 前缀递增 iterator& operator++() { ++it; return *this; } // 后缀递增(可选,但建议实现) iterator operator++(int) { iterator temp = *this; ++it; return temp; } // 解引用,返回Object& Object& operator*() { return *(*it).get(); } // 箭头运算符(可选,方便访问Object成员) Object* operator->() { return (*it).get(); } // 不等于判断,用于循环终止条件 bool operator!=(const iterator& other) const { return it != other.it; } }; // const版本迭代器,支持只读遍历 class const_iterator { private: std::vector<std::shared_ptr<Object>>::const_iterator it; public: explicit const_iterator(std::vector<std::shared_ptr<Object>>::const_iterator iter) : it(iter) {} const_iterator& operator++() { ++it; return *this; } const_iterator operator++(int) { const_iterator temp = *this; ++it; return temp; } const Object& operator*() const { return *(*it).get(); } const Object* operator->() const { return (*it).get(); } bool operator!=(const const_iterator& other) const { return it != other.it; } }; // 非const容器的begin/end iterator begin() { return iterator(list.begin()); } iterator end() { return iterator(list.end()); } // const容器的begin/end const_iterator begin() const { return const_iterator(list.begin()); } const_iterator end() const { return const_iterator(list.end()); } // 可选:标准的cbegin/cend,明确表示只读迭代器 const_iterator cbegin() const { return const_iterator(list.cbegin()); } const_iterator cend() const { return const_iterator(list.cend()); } };
方法二:用标准库迭代器适配器(简洁高效)
如果你不需要定制迭代器的额外行为,用std::transform_iterator可以省掉自己写迭代器类的麻烦,它会帮我们把shared_ptr<Object>转换成Object&。
#include <vector> #include <memory> #include <iterator> #include <functional> class Object {}; class List { public: std::vector<std::shared_ptr<Object>> list; // 定义转换函数:把shared_ptr<Object>转成Object& static Object& deref_shared_ptr(std::shared_ptr<Object>& ptr) { return *ptr.get(); } static const Object& deref_shared_ptr(const std::shared_ptr<Object>& ptr) { return *ptr.get(); } // 非const迭代器类型 using iterator = std::transform_iterator<decltype(&deref_shared_ptr), std::vector<std::shared_ptr<Object>>::iterator>; iterator begin() { return iterator(list.begin(), &deref_shared_ptr); } iterator end() { return iterator(list.end(), &deref_shared_ptr); } // const迭代器类型 using const_iterator = std::transform_iterator<decltype(&deref_shared_ptr), std::vector<std::shared_ptr<Object>>::const_iterator>; const_iterator begin() const { return const_iterator(list.begin(), &deref_shared_ptr); } const_iterator end() const { return const_iterator(list.end(), &deref_shared_ptr); } const_iterator cbegin() const { return const_iterator(list.cbegin(), &deref_shared_ptr); } const_iterator cend() const { return const_iterator(list.cend(), &deref_shared_ptr); } };
测试一下
现在你就可以像期望的那样用范围for遍历了:
int main() { List myList; myList.list.push_back(std::make_shared<Object>()); myList.list.push_back(std::make_shared<Object>()); // 非const遍历,可修改元素 for (Object& obj : myList) { // 对obj做操作 } // const遍历,只读访问 const List& constList = myList; for (const Object& obj : constList) { // 只读操作obj } return 0; }
⚠️ 注意:要确保list里的shared_ptr都不是空指针,否则解引用会导致未定义行为哦!
内容的提问来源于stack exchange,提问作者Dolfos
相关产品推荐
相关产品推荐

