从链接列表中删除元素,采访暴露了图书漏洞
Deleting Element from linked list, interviews exposed book bug?
Pg。29本《编程访谈》曝光的书中有以下从链接列表中删除元素的示例代码:
bool deleteElement(IntElement **head, IntElement *deleteMe)
{
IntElement *elem = *head;
if(deleteMe == *head){ /*special case for head*/
*head = elem->next;
delete deleteMe;
return true;
}
while (elem){
if(elem->next == deleteMe){
/*elem is element preceding deleteMe */
elem->next = deleteMe->next;
delete deleteMe;
return true;
}
elem = elem->next;
}
/*deleteMe not found */
return false;
}
我的问题是关于"delete deleteMe"语句,这是否达到了我们想要的效果,即实际删除该位置的元素,还是只是删除指向deleteMe元素的指针的副本?
delete deleteMe;
调用元素上的析构函数并释放其相关内存。这个代码是C++,顺便说一下
代码的其余部分更改数据结构列表,以取消元素与其邻居的链接。
您的问题已经得到了回答,但我不得不指出,如果我采访某人,他们以这种方式编写代码,我不会留下太大印象。
对于初学者来说,在这里使用指向指针的指针,虽然在C中是合理的,但在C++中完全没有必要。相反,我更希望看到对指针的引用。其次,常量正确的代码通常更可取。
bool deleteElement(IntElement const *&head, IntElement const *deleteMe)
{
IntElement *elem = head;
if(deleteMe == head){ /*special case for head*/
head = elem->next;
delete deleteMe;
return true;
}
while (elem){
if(elem->next == deleteMe){
/*elem is element preceding deleteMe */
elem->next = deleteMe->next;
delete deleteMe;
return true;
}
elem = elem->next;
}
/*deleteMe not found */
return false;
}
最后,我将再添加一个特殊情况,以避免对列表进行不必要的遍历。除非要删除的项恰好在列表的最后,否则可以避免遍历。让我们假设您的IntElement类似于:
struct IntElement {
int data;
IntElement *next;
};
在这种情况下:
bool simple_delete(IntElement *deleteMe) {
IntElement *temp = deleteMe->next;
deleteMe->data = temp->data;
deleteMe->next = temp->next;
delete temp;
return true;
}
他们在整个列表中搜索上一个元素,这样他们就可以删除后面的元素。相反,我们只需将下一个节点复制到当前节点中,然后删除下一个结点(注意:在某些情况下,交换数据而不是复制会更好/更快)。还要注意,如果其他东西可能持有指向下一个节点的指针,那么这可能会(非常彻底)破坏事物。
[值得一提的是,我最初是从Niklaus Wirth的算法+数据结构=程序中学到这项技术的,尽管我相信它起源于Knuth。]
不管怎样,一旦我们有了它,我们只需要在deleteElement
中添加一点代码来使用它,除非要删除的节点恰好是列表中的最后一个:
bool deleteElement(IntElement const *&head, IntElement *deleteMe) {
if (deleteMe->next != NULL)
return simple_delete(deleteMe);
// previous body of deleteElement
}
在原始文件总是具有线性复杂性的情况下,在大多数情况下它具有恒定的复杂性。通过使用一个末尾带有sentinel值而不是NULL指针的列表,您可以确保在所有情况下都保持恒定的复杂性(并且simple_delete
处理所有情况——您可以完全消除代码的其余部分)。
它实际上是在删除节点本身,而不是它的副本。
- 指向unique_ptr的指针 - 这是一个漏洞吗?
- 标头中有哪些固有的安全漏洞<filesystem>?
- 编译了一个recent-C++.因此,如果没有暴露std符号,请在旧系统上运行
- 需要帮助了解这个简短的C++程序及其漏洞
- 别名漏洞是否适用于签名字符?
- 为什么访问器函数必须是常量?漏洞在哪里?
- 如何将不属于 QObject 的枚举暴露给 QJSEngine?
- Cython:不暴露实施的一部分
- 通过重新加载DLL,避免使用DLL预加载漏洞,任何更好的方法
- 将ADA API暴露于C/C (可扩展方式)
- 同步线程安全的API,用于暴露缓存数据
- 与公开暴露的标头有关的C 项目结构
- 使用 Android NDK 演示 printf 或 __android_log_print 漏洞
- 在公共标头中使用非暴露类型的风险是什么?
- VULKAN,您可以直接暴露扩展名吗?
- 避免将静态变量暴露在默认函数参数中
- 将C 对象暴露于QML并收听更改事件
- 如何以相同的名称暴露无法直接暴露的C 函数
- 如何分析、查找和修复C++功能中的安全漏洞?
- 从链接列表中删除元素,采访暴露了图书漏洞