C++双向链表实现异常:仅能存储首个值,请求排查问题
你的双向链表实现核心问题分析与修正
我仔细梳理了你的代码,确实是LookingforRecord函数里存在几个关键错误,导致你只能保存第一个值,还无法找到已有的ID记录。下面逐个拆解问题并给出修正方案:
1. 新增节点时的data赋值完全错误
在LookingforRecord的add分支里,你写了:
p_node->data = m_p_node;
这明显是笔误!你本来要把传入的data值存在节点里,结果却把链表头指针m_p_node赋值给了uint8_t类型的data——这不仅会导致数据存储错乱,还可能触发类型转换的未定义行为。
正确写法:
p_node->data = data; // 使用add函数传入的data参数赋值
2. 新增节点时未正确更新链表头指针m_p_node
当向非空链表添加新节点时,你只设置了原头节点的p_prev指向新节点,但没有把m_p_node更新为新的头节点。这就导致后续遍历链表时,永远从最初的第一个节点开始,根本看不到新添加的节点。
原错误代码片段:
if ((p_node = new node) != 0) { memset(p_node, 0, sizeof(node)); p_node->ID = ID; p_node->data = m_p_node; // 这里也错了 p_node->p_next = m_p_node; if (m_p_node != 0) m_p_node->p_prev = p_node; else m_p_node = p_node; }
修正后,不管链表是否为空,都要把m_p_node指向新节点(因为你是在头部插入新节点):
if ((p_node = new node) != nullptr) { // 逐个初始化成员,比memset更安全(避免未来结构体添加非POD成员出问题) p_node->ID = ID; p_node->data = data; // 修正data赋值 p_node->p_prev = nullptr; p_node->p_next = m_p_node; if (m_p_node != nullptr) { m_p_node->p_prev = p_node; } // 必须更新头指针为新节点 m_p_node = p_node; }
3. LookingforRecord函数返回类型拼写错误
在List.cpp中,你写了:
list::Node * list::LookingforRecord(uint16_t ID, bool add)
但你的结构体是小写的node,不是大写的Node,这会导致编译错误。正确返回类型应为:
list::node * list::LookingforRecord(uint16_t ID, bool add)
4. 类成员函数printf与全局函数重名
你的类成员函数void list::printf(uint16_t ID)和标准库的全局printf重名了,会导致调用歧义。建议把成员函数名改成print或printRecord,同时在函数内部明确调用全局printf:
修正后的print函数:
void list::print(uint16_t ID) { node * p_node = LookingforRecord(ID, false); if (p_node != nullptr) { ::printf("p_node->ID %d \r\n", p_node->ID); ::printf("p_node->data %d \r\n", p_node->data); } }
5. 冗余全局变量需删除
你在List.cpp顶部定义的uint16_t ID = 0;完全没有被使用,建议删掉,避免混淆。
修正后的关键函数代码
LookingforRecord修正版
list::node * list::LookingforRecord(uint16_t targetID, bool add) { node * p_node = m_p_node; while (p_node != nullptr) { if (p_node->ID == targetID) { return p_node; } p_node = p_node->p_next; } if (add) { node* newNode = new node; if (newNode != nullptr) { newNode->ID = targetID; newNode->data = 0; // 先初始化,后续add函数会覆盖 newNode->p_prev = nullptr; newNode->p_next = m_p_node; if (m_p_node != nullptr) { m_p_node->p_prev = newNode; } m_p_node = newNode; } return newNode; } return nullptr; }
add函数修正版
uint8_t list::add(uint16_t ID, uint8_t data) { node * p_node = LookingforRecord(ID, true); if (p_node != nullptr) { p_node->data = data; return ID; // 按你原逻辑返回ID作为batch_size } return 0; // 添加失败返回0 }
额外优化建议
- 尽量用
nullptr代替0/NULL表示空指针,这是C++11及以后的标准写法,类型更安全。 - 可以给
node结构体添加构造函数,简化初始化:
新增节点时直接写struct node { uint16_t ID; uint8_t data; node * p_prev; node * p_next; node(uint16_t id, uint8_t d) : ID(id), data(d), p_prev(nullptr), p_next(nullptr) {} };new node(ID, data),代码更简洁。
内容的提问来源于stack exchange,提问作者Ale
相关产品推荐
相关产品推荐

