在有关Linus Torvalds的采访中,他分享了拥有“好品味”的重要性。他用以下代码解释了良好的品味。
“味道不好”的代码
remove_list_entry(entry)
{
prev = NULL;
walk = head;
// Walk the list
while (walk != entry) {
prev = walk;
walk = walk->next;
}
// Remove the entry by updating the head
// or the previous entry
if (!entry)
head = entry->next;
else
prev-next = entry->next;
}
“好味道”的代码
remove_list_entry(entry)
{
// The "indirect" pointer points to the
// *address* of the thing we'll update
indirect = &head;
// Walk the list, looking for the thing that
// points to the thing we want to remove
while ((*indirect) != entry)
indirect = &(*indirect)->next;
// .. and just remove it
*indirect = entry->next;
}
两个示例都没有使用free()
释放要删除的节点的内存。有人可以告诉我为什么用这种方式编写代码吗?还是我对C或链表的概念有误?
答案 0 :(得分:3)
注意此功能的语义也很重要。它旨在从列表中删除一个节点,而不是像您在问题中建议的那样删除该节点。至少函数名称暗示了这一点。如果它删除该节点却不宣传该语义,我会感到惊讶。
此外,我们无法孤立地知道对象的分配方式,因此该函数无法合理地假设它是堆对象,而free()
则不能假定它-如果对象是静态的,则会导致运行时错误。
调用者可能正在从列表中删除该对象并继续使用它,此功能的职责是维护 list 而不是列表中具有独立存在的对象。 entry
的所有者有责任管理其内存。
答案 1 :(得分:1)
在这种情况下,极简主义体现了良好的品味。第二个例子比第一个例子华丽,但意义重大。不良代码有一些错误,但要点是多余的变量和if语句是多余的。
味觉是一种主观素质,有很多理由赞成这两种方法。对我而言,品味一直与可读性有关。可读性并没有明确支持这两种方法-TLDR与Too Complex;没打扰(TC; DB)。
编译器技术对品味有影响。很久以前,当需要进行窥孔优化时,最好使用第二个版本。它生成的代码少得多。在不太过去的日子里,编译器非常喜欢数据流分析,并且喜欢第一个版本,因为它显然没有将指针追逐隐藏的别名(与第二个版本不同)。现代编译器使内存和CPU的工作量大为提高,因此可以更好地进行别名检查,因此回到了第一个。即使在您的示例中,它仍然有3条指令不同。