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

Course类拷贝构造器问题:拷贝对象修改致原对象变更

问题描述

我正在为Course类实现拷贝构造器,当前实现导致部分单元测试失败。单元测试显示,用已有Course对象初始化新对象后,修改新对象时原对象也会被改变,二者本应相互独立。我无法修改单元测试,需修复拷贝构造器。

相关代码

Course类定义

class Course {
    //** You may not change the declarations in this private: area.
    CourseName name;           ///< 课程名称
    int numberOfPrerequisites; ///< 当前数组中的前置课程数量
    int maxPrerequisites;      ///< 数组可容纳的最大前置课程数量
    CourseName * prereqs;  
};

当前拷贝构造器代码

Course::Course(const Course& other)
    : name(other.name), numberOfPrerequisites(other.numberOfPrerequisites),
      maxPrerequisites(other.maxPrerequisites), prereqs(new CourseName[other.maxPrerequisites])
{
    // 复制所有前置课程
    for (int i = 0; i < numberOfPrerequisites; ++i)
    {
        prereqs[i] = other.prereqs[i];
    }
}

已尝试的运算符重载代码

等于运算符

bool Course::operator==(const Course& other) const
{
    return name == other.name;
}

赋值运算符

Course& Course::operator=(const Course& other)
{
    if (this == &other)
        return *this;

    name = other.name;
    numberOfPrerequisites = other.numberOfPrerequisites;
    maxPrerequisites = other.maxPrerequisites;

    delete[] prereqs;

    prereqs = new CourseName[other.maxPrerequisites];

    // 将源对象的前置课程复制到新对象
    for (int i = 0; i < numberOfPrerequisites; ++i)
    {
        prereqs[i] = other.prereqs[i];
    }

    return *this;
}
修复方案

问题核心是深拷贝不彻底:你已经为prereqs数组分配了新的内存空间,但如果CourseName类本身包含动态分配的资源(比如指针)且未实现正确的深拷贝逻辑(拷贝构造器、赋值运算符),那么数组中每个CourseName对象的拷贝只是浅拷贝——新旧对象的CourseName会共享底层资源,修改新对象的元素自然会影响原对象。

方案1:修复CourseName的深拷贝(若有权限修改)

给CourseName实现正确的拷贝构造器和赋值运算符,确保其内部的动态资源被完整复制,而非仅复制指针。示例如下(假设CourseName内部有动态分配的字符串):

class CourseName {
    char* name;
public:
    CourseName(const CourseName& other) {
        // 分配新内存并复制内容
        name = new char[strlen(other.name) + 1];
        strcpy(name, other.name);
    }

    CourseName& operator=(const CourseName& other) {
        if (this == &other) return *this;
        // 释放原有内存
        delete[] name;
        // 分配新内存并复制
        name = new char[strlen(other.name) + 1];
        strcpy(name, other.name);
        return *this;
    }

    ~CourseName() {
        delete[] name;
    }
};

方案2:在Course层手动完成深拷贝(无法修改CourseName时)

如果不能修改CourseName,则在Course的拷贝逻辑中,通过CourseName的拷贝构造函数创建全新的对象,替换简单的赋值操作:

修改拷贝构造器:

Course::Course(const Course& other)
    : name(other.name), numberOfPrerequisites(other.numberOfPrerequisites),
      maxPrerequisites(other.maxPrerequisites), prereqs(new CourseName[other.maxPrerequisites])
{
    for (int i = 0; i < numberOfPrerequisites; ++i)
    {
        // 用拷贝构造创建新的CourseName对象,而非浅赋值
        prereqs[i] = CourseName(other.prereqs[i]);
    }
}

同步修改赋值运算符:

Course& Course::operator=(const Course& other)
{
    if (this == &other)
        return *this;

    name = other.name;
    numberOfPrerequisites = other.numberOfPrerequisites;
    maxPrerequisites = other.maxPrerequisites;

    delete[] prereqs;
    prereqs = new CourseName[other.maxPrerequisites];

    for (int i = 0; i < numberOfPrerequisites; ++i)
    {
        prereqs[i] = CourseName(other.prereqs[i]);
    }

    return *this;
}

额外注意:添加析构函数

确保Course类有正确的析构函数释放prereqs数组,避免内存泄漏:

Course::~Course()
{
    delete[] prereqs;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 04:17:21