C++中拷贝迭代器导致成员值异常的问题求助
解决DFS迭代器拷贝时成员变量异常的问题
看起来你遇到的核心问题是自定义迭代器在拷贝过程中,内部关联的容器被意外复制,导致后续解引用时访问的是副本而非原容器的节点,最终出现neighbours为空、_vertices值异常的情况。下面是具体的分析和解决方案:
问题根源
你的自定义迭代器类大概率是持有了容器的拷贝而非引用/指针。当调用_vertices.begin()或next()生成迭代器时,迭代器内部会复制一份_vertices容器;后续操作这个迭代器时,实际访问的是副本容器里的节点,自然和原容器的节点状态(比如neighbours)不一致。
解决方案:重构迭代器类,使用容器引用
你需要修改迭代器的设计,让它内部持有原容器的引用,确保所有迭代器实例都关联到同一个原容器。以下是示例实现:
1. 修正迭代器类的定义
class iterator { private: // 关键:用引用关联原容器,而非拷贝 vector<node>& _vertices; size_t _current_idx; public: // 构造函数必须传入原容器的引用和当前索引 iterator(vector<node>& vertices, size_t idx) : _vertices(vertices), _current_idx(idx) {} // 拷贝构造函数默认即可,引用会自动关联到原容器 iterator(const iterator& other) = default; // 解引用操作:返回原容器中对应节点的引用 node& operator*() { return _vertices[_current_idx]; } const node& operator*() const { return _vertices[_current_idx]; } // ->操作符:返回原容器中节点的指针 node* operator->() { return &_vertices[_current_idx]; } const node* operator->() const { return &_vertices[_current_idx]; } // 迭代器自增操作(按需实现) iterator& operator++() { ++_current_idx; return *this; } // 相等性判断:必须检查是否指向同一个容器 bool operator==(const iterator& other) const { return &_vertices == &other._vertices && _current_idx == other._current_idx; } bool operator!=(const iterator& other) const { return !(*this == other); } };
2. 修正容器的begin()方法
确保你的容器类(包含_vertices的类)的begin()返回正确关联原容器的迭代器:
class Graph { private: vector<node> _vertices; // ...其他成员 public: iterator begin() { return iterator(_vertices, 0); } const_iterator begin() const { return const_iterator(_vertices, 0); } // 自定义获取指定索引的迭代器,替代std::next更直观 iterator get_iterator_at(size_t idx) { return iterator(_vertices, idx); } };
3. 调整DFS相关函数
确保depthFirst和depthFirst_aux中使用的迭代器都关联原容器:
vector<iterator> depthFirst(node& gn) { vector<iterator> result; unmark(); // 重置所有节点的访问标记,确保操作原容器的节点 // 直接用节点的_index生成迭代器,避免next可能的边界问题 auto it = get_iterator_at(gn._index); depthFirst_aux(it, result); return result; } // 传引用避免不必要的迭代器拷贝(更高效) void depthFirst_aux(iterator& it, vector<iterator>& result) { mark(*it); // 标记原容器中的节点为已访问 result.push_back(it); // 遍历原节点的邻居,生成对应迭代器 for (size_t neighbour_idx : it->neighbours) { auto neighbour_it = get_iterator_at(neighbour_idx); if (!isMarked(*neighbour_it)) { depthFirst_aux(neighbour_it, result); } } }
额外检查点
- 确认
gn._index是_vertices的有效索引,避免越界访问导致的未定义行为。 - 检查
unmark()和mark()函数是否操作的是原_vertices容器中的节点,而非其他副本。
这样修改后,所有迭代器都会关联到原容器,解引用时访问的就是正确的节点,neighbours等成员变量也会恢复正常。
内容的提问来源于stack exchange,提问作者fahad aijaz
相关产品推荐
相关产品推荐

