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

如何为包装LinkedList的C++模板LStack类实现拷贝函数?

你当前的copy函数实现存在两个核心问题:

  1. 不可用memcpy拷贝包含指针成员的自定义类:你的LStack内部持有LinkedList实例,而LinkedList包含head/tail/current三个指针成员,memcpy是浅字节拷贝,会导致副本和原栈的内部指针指向同一块内存,任意一方销毁释放内存后,另一方就会触发野指针错误。
  2. 返回堆上对象的引用会导致内存泄漏:你在copy函数内new了栈实例,返回引用后调用方很难感知需要手动释放,极易出现内存泄漏。

以下是完全符合作业限制的解决方案:

第一步:为LinkedList实现拷贝构造函数

因为LStack的功能基于LinkedList实现,且LStack的成员函数可以访问自身私有成员data,我们只需要先给底层LinkedList实现正确的深拷贝构造即可:

// 在LinkedList类的public声明中添加拷贝构造函数声明
LinkedList(const LinkedList<T>& src);

// 拷贝构造函数实现
template <typename T>
LinkedList<T>::LinkedList(const LinkedList<T>& src)
{
    head = tail = current = nullptr;
    if (src.isEmpty())
        return;
    // 保存源链表原遍历位置,避免拷贝操作影响源链表的状态
    Node<T>* original_current = src.current;
    // 遍历源链表所有节点,深拷贝到当前链表
    src.moveCurrentToHead();
    while (true)
    {
        addToTail(src.getCurrentData());
        if (src.getCurrentData() == src.getTail())
            break;
        src.moveCurrentForward();
    }
    // 恢复源链表的遍历位置
    src.current = original_current;
}

同时建议补充LinkedList的拷贝赋值运算符,避免后续赋值操作出现浅拷贝问题。

第二步:修改LStack的拷贝逻辑

你可以选择两种方案,都符合作业要求:

方案A:实现LStack拷贝构造(更符合C++习惯,无需单独copy函数)

// 在LStack类的public声明中添加拷贝构造声明
LStack(const LStack<T>& src);

// 拷贝构造实现
template <typename T>
LStack<T>::LStack(const LStack<T>& src)
{
    // 直接调用LinkedList的拷贝构造完成深拷贝
    data = src.data;
}

实现后你可以直接在<<运算符重载中直接构造副本:

template <typename T>
ostream& operator << (ostream& out, const LStack<T>& LS)
{
    if (LS.isEmpty())
    {
        out << "Stack is empty.";
        return out;
    }
    // 直接用拷贝构造生成副本,不需要单独调用copy函数
    LStack<T> LScopy = LS;
    while (!LScopy.isEmpty())
    {
        out << "(";
        out << LScopy.peek().get_licence();
        out << ", ";
        out << LScopy.peek().get_charge();
        out << ") ";
        LScopy.pop();
    }
    return out;
}

方案B:保留单独copy函数的实现

如果你需要保留单独的copy函数,修改如下:

// 修改LStack类中copy函数的声明,返回值改为对象,参数不需要传自身,加const保证不修改原栈
LStack<T> copy() const;

// copy函数实现
template <typename T>
LStack<T> LStack<T>::copy() const
{
    LStack<T> res;
    res.data = this->data;
    return res;
}

调用方式和你原来的代码基本一致,只需要修改调用方法:

LStack<T> LScopy = LS.copy();

额外注意点

  • 建议把LStack的push函数参数改为const T& obj,避免无法传入临时对象/const对象
  • 建议把peek、isEmpty、size这类不修改栈的方法都加const修饰,保证const正确性
  • 不需要手动删除<<运算符中的LScopy,它是局部栈变量,函数执行结束会自动调用析构函数释放资源,不会产生内存泄漏

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 09:57:02