【问题标题】:How to iterate properly across a const set?如何正确地遍历 const 集?
【发布时间】:2010-05-08 22:50:52
【问题描述】:

我正在开发一个应该表示图形的程序。我的问题出在我的 printAdjacencyList 函数中。基本上,我有一个 Graph ADT,它有一个成员变量“nodes”,它是该图节点的映射。每个节点都有一组 Edge* 到它所连接的边。我正在尝试遍历图中的每个节点和节点的每个边。

void MyGraph::printAdjacencyList() {
std::map<std::string, MyNode*>::iterator mit;
std::set<MyEdge*>::iterator sit;

for (mit = nodes.begin(); mit != nodes.end(); mit++ ) {
    std::cout << mit->first << ": {";
    const std::set<MyEdge*> edges = mit->second->getEdges();
    for (sit = edges.begin(); sit != edges.end(); sit++) {
        std::pair<MyNode*, MyNode*> edgeNodes = *sit->getEndpoints();
    }
}
std::cout << " }" << std::endl;
}

getEdges 声明为:

const std::set<MyEdge*>& getEdges() { return edges; };

get Endpoints 声明为:

const std::pair<MyNode*, MyNode*>& getEndpoints() { return nodes; };

我得到的编译器错误是:

MyGraph.cpp:63: error: request for member `getEndpoints' in 
`*(&sit)->std::_Rb_tree_const_iterator<_Tp>::operator->
[with _Tp = MyEdge*]()', which is of non-class type `MyEdge* const'

MyGraph.cpp:63: warning: unused variable 'edgeNodes'

我发现这可能意味着我在某处滥用了 const,但我无法弄清楚我的一生在哪里。任何信息,将不胜感激。谢谢!

【问题讨论】:

  • 除非你做这个项目是为了家庭作业或娱乐,否则我建议你只使用 boost 库图形表示。
  • 是的,这是一堂课的功课,所以没有提升美感 =(
  • @Jared 祝你好运,然后:) 你也可以考虑用“作业”标签标记这类问题,这样人们就会知道。
  • @Jared @Amir 别担心。如果您不使用 BGL,您可以避免很多头痛。从您自己的模拟图功能转移到 BGL 就像从 stdio.h 转移到 iostream。有一天你可能会感激不尽,但在那之前,你口中说出的脏话数量不会让英国足球迷感到羞耻。
  • 您说nodes 是一张地图,但在getEndpoints 中您将其返回为std::pair。这是怎么回事?

标签: c++ iterator constants


【解决方案1】:

尝试将sit 更改为const_iterator。当您使用它时,也将mit 更改为const_iterator。此外,getEdges()getEndpoints() 应该是 const functions。最后,由于operator-&gt;() 的优先级高于一元operator*(),您可能想在内循环中使用edgeNodes = (*sit)-&gt;getEndPoints()

问题不大,但您应该考虑将迭代器实例作为循环的本地实例。

【讨论】:

  • 我已将两个迭代器都更改为 const_iterators 并将 getEdges 和 getEndpoints 重新定义为 const 函数,编译器错误没有变化。
  • @Jared 我更新了答案。我认为这些更改应该让编译器平静下来。
  • 如果在这些错误之后仍然出现这些错误,如果将这些访问器的返回类型更改为按值返回,而不是按 const-reference 返回,会发生什么情况?
  • 最后一条评论是在 (*sit)->getEndpoints() 建议之前。这解决了我的问题,谢谢!
【解决方案2】:

如果没有可编译的东西,很难说出任何确定的东西,但是

const std::set<MyEdge*>& getEdges() { return edges; };

const std::pair<MyNode*, MyNode*>& getEndpoints() { return nodes; };

技术上应该是 const 方法,因为它们不会修改类并返回 const 引用。

const std::set<MyEdge*>& getEdges() const { return edges; };
const std::pair<MyNode*, MyNode*>& getEndpoints() const { return nodes; };

这与const_iterator 结合可能会解决您的常量问题。


但是,您的特定错误可能是 *it-&gt;foo() = *(it-&gt;foo())(*it)-&gt;foo() 不同

【讨论】:

  • (*it)->foo() 成功了!括号到底是做什么的?只是告诉编译器将取消引用的迭代器视为一个对象?
  • 他们改变了优先级。 -> 运算符的优先级高于 * 运算符,因此首先计算它。但是您需要首先评估 *,因此您将其与括号内的操作数括起来。
【解决方案3】:

s/std::set&lt;MyEdge*&gt;::iterator sit;/std::set&lt;MyEdge*&gt;::const_iterator sit;/

mit 也是如此。换句话说,const_iterator 就是你需要的。

【讨论】:

  • 我已经把两个迭代器都改成了 const_iterator 错误是完全一样的。
猜你喜欢
  • 2022-12-01
  • 2011-09-18
  • 2019-11-30
  • 2013-03-28
  • 2012-03-20
  • 1970-01-01
  • 2014-12-11
相关资源
最近更新 更多