我正在学习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 变量,不要?谢谢!
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
循环。
正如 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();