void removeDuplicateWithHashtable(LinkedListElement<char> *head)
{
LinkedListElement<char> *runner = head;
LinkedListElement<char> *previous = nullptr;
hash_map<char, bool> record;
while (runner) {
if (record.count(runner->Data) == 0) {
pair<char, bool> item(runner->Data,true);
record.insert(item);
}else
{
free(runner);
previous->Next = runner->Next;
}
previous=runner;
runner=runner->Next;
}
}
最初我认为会有错误。因为在free(runner)
中,如果我释放内存,我无法访问runner-&gt; Next。
但GCC编译器运行成功。
实际上如果我改变自由以删除跑步者,它也是正确的。 我可以问原因可能是免费或删除只是告诉你内存可用没有实际清除数据里面,所以你也可以访问下一步。 我可以问一下如何改进吗?
答案 0 :(得分:3)
这不是编译错误,但问题(未定义的行为)将在运行时显现出来。如果您选择在未分配的内存上调用free
,编译器将不会阻止您。
答案 1 :(得分:3)
编译器无法检测到这种逻辑错误!相反,该程序具有未定义的行为,其中可能包括运行看似正常,崩溃或生成各种垃圾。有很多(并且我不能强调那么多,如LOT)导致未定义行为的情况
答案 2 :(得分:1)
您的程序可以正常运行,因为free()
仅将某些内存标记为空闲,但实际上并未覆盖它。由于这个原因,你的解决方案在大多数情况下都能正常运行,就像在你的功能中没有使用任何新内存一样。 (至少在单线程环境中。)
另一方面,我会去从根本上改变这样的功能:
template<typename _Tp>
void unique(forward_list<_Tp>& list)
{
unordered_map<_Tp, bool> record;
auto la=list.before_begin();
for(auto it=list.begin(); it!=list.end(); ++it)
{
if(record.find(*it)==record.end())
record[*++la] = true;
else
list.erase_after(la);
}
}
你甚至可以写这个:
template<typename _Tp>
void unique(forward_list<_Tp>& list)
{
unordered_map<_Tp, bool> record;
auto la=list.before_begin();
for(auto e: list)
{
if(record.find(e)==record.end())
record[*++la] = true;
else
list.erase_after(la);
}
}
但我认为这可能有点太多了,因为它并没有反映出我们需要追逐一个元素。
我发生根本性变化的原因:
在C ++ free()
中称为delete
。它与new
配对使用(在c ++中使用,而不是malloc()
或calloc()
)。 delete
的使用方式如下:
删除跑步者;
//和new一样使用:
Some_type * p = new Some_type();
STL已经有了一个LinkedList,所以使用它是有意义的。它被称为std::forward_list。您想使用erease_after
, with a nice example。
您想使用std :: unsorted_map而不是hash_map(再次,因为它在STL中)。最好的始终是标准解决方案。
类的主要目的之一是隐藏必要的指针活动,所以在函数头中我宁愿使用引用而不是指针,所以至少你的函数应该是
void removeDuplicateWithHashtable(LinkedListElement&amp; head)