我有这个功能:
QLinkedList<hTag>::iterator *lookForLastHTag(hTags tag, QLinkedList<hTag> openedTags){
QLinkedList<hTag>::iterator *i = new QLinkedList<hTag>::iterator();
*i = openedTags.end();
while(*i != openedTags.begin()){
*i-=1;
if ((*(*i)).tag == tag)
return i;
}
return nullptr;
}
用QT框架编写。它向后搜索hTag
的单链表,这是一个名为hTags
的枚举中的特定标记(请注意,前一个是结构,第二个是枚举类)。
hTag
结构以这种方式定义:
struct hTag{
hTags tag;
int hierarchy;
};
而hTags枚举类只定义了一些标记。
问题是,在函数返回i
指针后,它会被其他数据奇怪地覆盖。我不明白,因为我已经在堆中为该迭代器动态分配了空间,以避免出现此问题。我不明白为什么指针i
的内容(不是它指向的东西,i
内的32位数字)正确返回(在32位的意义上)指针内的数字被正确复制到函数外部)。但是,i
(指针)的内容不是。在函数结束之后,它会被垃圾覆盖,即使它在堆上声明并且不应该受到函数结束的影响
你能帮我解决一下这个问题吗?
提前致谢。
答案 0 :(得分:1)
问题是按值传递列表:
QLinkedList<hTag>::iterator *lookForLastHTag(hTags tag, QLinkedList<hTag> openedTags)
// ^^
这会导致创建列表的副本,一旦控制流从函数返回就会再次销毁。
然后返回的迭代器实例引用一个不再存在的列表,如果使用它,则以未定义的行为结束。
为了避免这种情况,你需要将列表作为引用或指针传递,最好是一个const(因为你不修改它;但是,你也需要返回一个const_iterator):
QLinkedList<hTag>::const_iterator* lookForLastHTag(hTags tag, QLinkedList<hTag> const& openedTags)
// ^ ^ ^(!!!)
然后你的迭代器对象将指向传递给函数的原始列表,你可以使用第一个点。
此外,您实现了内存泄漏:如果未找到任何元素,则迭代器仍未使用,因此您必须在返回之前再次将其删除:
delete i;
return nullptr;
但是,用户通过在不再需要时忘记删除返回的指针来创建进一步的内存泄漏存在一些不可忽视的风险,尤其是因为这是使用迭代器的非常异常方式(当然,不再是你的责任,但你可以从一开始就通过更好的设计来避免这种情况):
QLinkedList<hTag>::const_iterator lookForLastHTag(hTags tag, QLinkedList<hTag> const& openedTags)
// ^ (no pointer!)
{
QLinkedList<hTag>::const_iterator i = openTags.end();
while(i != openTags.begin())
{
--i;
if(i->tag == tag)
return i;
}
return openTags.end();
}
由于副作用,代码变得不那么复杂,你不同意吗?
附注:您可能想要查看std::find;不需要重新发明轮子......