为什么重命名我的变量会阻止段错误?

Mat*_*att 1 c++ iteration iterator segmentation-fault

在给定起始节点的迭代器的情况下,我实现了一个深度优先搜索算法来遍历我的图形.

文档摘要:

  • GraphIter的typedefGraph::iterator
  • Graph课程延伸 map<string, Node>
  • start->second.edges() 回报 set<string>

此代码将导致一个分段错误,如果尺寸start->second.edges()0:

(为简洁起见,我截断了不相关的部分,包括递归调用.)


糟糕的代码

void Graph::dfs(GraphIter start)
{
    cout << "EDGES SIZE: " << start->second.edges().size() << endl;

    for (set<string>::iterator it = start->second.edges().begin();
          it != start->second.edges().end(); ++it)
    {
        GraphIter iter = this->find(*it);     // <--- SEGMENTATION FAULT
    }
}
Run Code Online (Sandbox Code Playgroud)

现在看看当我start->second.edges()进入局部变量时会发生什么:不再有段错!

这是不生成段错误的代码:


好的代码

void Graph::dfs(GraphIter start)
{
    set<string> edges = start->second.edges();       // <--- MAGIC TRICK
    cout << "EDGES SIZE: " << edges.size() << endl;

    for (set<string>::iterator it = edges.begin();
          it != edges.end(); ++it)
    {
        GraphIter iter = this->find(*it);
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,不同的是,在良好的代码,当大小的组字符串的(从edges()法)是0,则for循环永远不会在第二种情况下输入的.但在第一种情况下,for循环仍然至少执行一次,直到它意识到它不能取消引用it变量.

为什么这些不同?他们不能访问相同的内存部分吗?

CB *_*ley 6

因为edges()返回一个set值,start->second.edges().begin()并将start->second.edges().end()迭代器返回到不同的容器,因为每次调用都会返回edges()一个新set的返回值.

通过创建一个命名变量的单一副本可以确保迭代器都来自同一个容器,你可以从有效方式迭代begin()end().