【问题标题】:Segmentation fault in list<Object*> iterator [closed]list<Object*> 迭代器中的分段错误[关闭]
【发布时间】:2018-03-23 17:26:53
【问题描述】:

我正在学习 C++,但现在我遇到了迭代器的问题。这是我的情况:我这里有这段代码。

// std::list<Dragon*> dragons = cave.getDragons();
for (std::list<Dragon*>::iterator it = cave.getDragons().begin(); it != cave.getDragons().end(); it++){
        os << std::endl << (*it)->getName();
}

它返回一个分段错误。这是我的列表和我的 getDragons() 方法:

std::list<Dragon*> dragons;
std::list<Dragon*> getDragons() const {return dragons;}

我的问题是...为什么我会出现这样的分段错误,但是如果我使用评论了的 dragons 变量,不要这样做?谢谢!

【问题讨论】:

  • 你有一个Dragon*s 的列表,然后在它的开头创建一个迭代器,然后删除该列表并让它被销毁。然后你继续将它与一个迭代器进行比较,以得到一个类似的销毁列表。无论如何,使用基于范围的 for 循环(foreach 循环:for (auto* dragon : cave.getDragons())
  • getDragons() 返回一个副本。也许您需要参考?
  • 有一个测试器,它必须使用以下代码:auto it = cave-&gt;getDragons().begin(); 它适用于我的第一个解决方案,但不适用于测试器
  • 好吧,也许我不得不说它工作一次,而且只有一次。我可以读取列表中的第一个元素,但不能读取第二个。

标签: c++ list c++11 iterator segmentation-fault


【解决方案1】:

getDragons() 按值返回std::list,因此每次调用getDragons() 时,都会得到dragons 列表的副本。因此,您的 for 循环正在比较来自不同临时 std::list 对象的迭代器,并将尝试取消引用无效的迭代器。

你需要做更多这样的事情:

std::list<Dragon*> dragons = cave.getDragons();
for (std::list<Dragon*>::iterator it = dragons.begin(); it != dragons.end(); it++){
    os << std::endl << (*it)->getName();
}

或者,如果您使用的是 C++11 或更高版本,请改用 for-range 循环:

for (Dragon *dragon : cave.getDragons()) {
    os << std::endl << dragon->getName();
}

否则,您需要更改 getDragons() 以通过引用返回 std::list

const std::list<Dragon*>& getDragons() const {return dragons;}

那么你原来的for 代码就可以工作了,尽管它仍然会在每次循环迭代时调用getDragons()。最好将单个调用的结果缓存到局部变量:

const std::list<Dragon*> &dragons = cave.getDragons();
for (std::list<Dragon*>::const_iterator it = dragons.begin(); it != dragons.end(); it++){
    os << std::endl << (*it)->getName();
}

或者,使用上面显示的相同 C++11 for-range 循环。

【讨论】:

    【解决方案2】:

    正如 Remy 解释的那样,您的潜在错误是使用列表副本(这不仅容易出错而且效率低下)。因此,正确的解决方法是从不创建此类副本(Remy 的回答仍然建议这样做)。为此,您的 getDragons() 方法应该返回一个引用。

    struct Cave
    {
      /* ... */
      std::list<const Dragon*> const&getDragons() const;
    };
    

    此外,您应该尽可能使用 auto 关键字(当然至少使用 2011 年标准)。

    for(auto const&dragon : cave.getDragons())
      os << std::endl << dragon.getName();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-09
      • 2017-10-10
      • 2015-02-05
      • 2016-03-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多