You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++链表实现拷贝构造函数触发读访问错误问题排查

问题1:DeleteList方法存在致命逻辑错误

你当前DeleteList中的代码逻辑完全无效:

temp->data = nullptr;
delete temp->data;

你先把data指针置为空,再delete空指针没有任何实际释放作用,原本data指向的堆内存会直接泄漏。
你之前直接delete temp->data报错的原因是Node创建时没有对data指针做初始化,未初始化的指针是野指针,直接delete野指针必然触发断言错误。正确的处理逻辑是Node构造时就把data和next都初始化为nullptr,释放时只有确认data指向有效堆内存再执行delete。
正确的DeleteList写法:

void DeleteList()
{
    Node<T>* temp;
    while (head_ != nullptr)
    {
        temp = head_;
        head_ = head_->next;
        // 仅非空指针执行释放
        if (temp->data != nullptr) {
            delete temp->data;
        }
        delete temp;
    }
}

同时需要给Node补充默认构造函数,避免野指针:

template <class T>
struct Node
{
   T* data;
   Node* next;
   // 新增默认构造,初始化成员为nullptr
   Node() : data(nullptr), next(nullptr) {}
   // 可选:带参数构造,创建节点时直接完成内存分配和值拷贝
   Node(const T& val) : next(nullptr) {
       data = new T(val);
   }
};

问题2:拷贝赋值运算符为浅拷贝,直接触发访问冲突

你当前的拷贝赋值逻辑是直接复制源节点的data指针d_node->data = (source.head_)->data,这会导致两个链表的节点指向同一块T类型的内存。当任意一方链表被销毁,DeleteList会释放这块内存,另一方的data就变成野指针,访问时就会抛出读访问冲突,这是你报错的根本原因。
拷贝时需要做深拷贝,给目标节点的data单独分配堆内存、复制值而不是复制指针,正确的拷贝赋值调整如下:

List342& operator=(const List342& source)
{
    if (this == &source)
    {
        return *this;
    }

    DeleteList();

    if (source.head_ == nullptr)
    {
        return *this;
    }

    Node<T>* s_node = source.head_;
    // 头节点深拷贝
    head_ = new Node<T>(*(s_node->data));
    Node<T>* d_node = head_;
    s_node = s_node->next;

    while (s_node != nullptr)
    {
        d_node->next = new Node<T>(*(s_node->data));
        d_node = d_node->next;
        s_node = s_node->next;
    }
    return *this;
}

如果不准备给Node加带参构造,也可以手动分配内存完成拷贝:

d_node->data = new T(*(s_node->data));

调整后两个链表的data指针指向独立内存,不会出现释放后访问的冲突。

内容的提问来源于stack exchange,提问作者DerpyDays

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 02:09:02