列表<object *>迭代器中的分段错误

时间:2017-10-11 22:11:58

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

我正在学习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;}

我的问题是......为什么我会像这样做一个Segmentation错误,但是如果我使用龙变量,这是评论,不是吗?谢谢!

2 个答案:

答案 0 :(得分: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循环。

答案 1 :(得分:0)

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

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

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

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