复制动态阵列并使用过载的操作员删除原件

Copying a dynamic array and deleting the original using an overloaded operator

本文关键字:操作员 删除 阵列 动态 复制      更新时间:2023-10-16

我正在创建一个可以跟踪学生的课程。在此课程中,我使用一个Overloaded =复制这些学生对象。要跟踪他们的课程,我使用一个动态数组。阵列的副本很好。但是,在清除学生对象的变量时,从之前复制的任何对象也都会擦拭数组。这是代码:

#include <iostream>
#include <string>
using namespace std;
class Student
{
    string name;                //Name
    string* classList = NULL;   //Empty array to store class names in
    int numClasses = 0;         //Number of classes
public:
    void InputData()
    {
        cout << "Enter student name: " << endl;                         //Input Name
        cin >> name;
        cout << "Enter number of classes: " << endl;                    //Input classes
        cin >> numClasses;
        classList = new string[numClasses];                             //Define array size
        for (int i = 0; i < numClasses; i++)                            //For every spot in array, name class
        {
            cout << "Enter name of class " << (i + 1) << ":" << endl;   //Name class
            cin >> classList[i];
        }
    };
    void OutputData()
    {
        cout << "Name: " << name << endl;                               //Output data
        cout << "Number of Classes: " << numClasses << endl;
        for (int i = 0; i < numClasses; i++)                            //Cycle through and output classes
        {
            cout << "Class " << i << ": " << classList[i] << endl;
        }
    };
    void ResetClasses()
    {
        name = "";
        delete[] classList;         //Free Memory
        classList = NULL;           //Clear array
        numClasses = 0;
    };
    Student operator =(Student& student)                //Overload =
    {
        this->name = student.name;
        this->classList = student.classList;
        this->numClasses = student.numClasses;
        return *this;
    };
};
int main()
{
    Student s1, s2;
    s1.InputData();               // Input data for student 1
    cout << "Student 1's data:" << endl;
    s1.OutputData();              // Output data for student 1
    s2 = s1;
    cout << "Student 2's data after assignment from student 1:" << endl;
    s2.OutputData();              // Should output same data as for student 1
    s1.ResetClasses();
    cout << "Student 1's data after reset:" << endl;
    s1.OutputData();              // Should have no classes
    cout << "Student 2's data, should still have original classes:" << endl;
    s2.OutputData();              // Should still have original classes
}

主要罪犯几乎可以肯定是这两个

中的任何一个
        void ResetClasses()
        {
            name = "";
            delete[] classList;         //Free Memory
            classList = NULL;           //Clear array
            numClasses = 0;
        };
        Student operator =(Student& student)                //Overload =
        {
            this->name = student.name;
            this->classList = student.classList;
            this->numClasses = student.numClasses;
            return *this;
        };

程序的输出是:

Enter student name:
ERIC
Enter number of classes:
2
Enter name of class 1:
C++
Enter name of class 2:
C
Student 1's data:
Name: ERIC
Number of Classes: 2
Class 0: C++
Class 1: C
Student 2's data after assignment from student 1:
Name: ERIC
Number of Classes: 2
Class 0: C++
Class 1: C
Student 1's data after reset:
Name:
Number of Classes: 0
Student 2's data, should still have original classes:
Name: ERIC
Number of Classes: 2
Class 0:
Class 1:

造成这一点我会做什么?

Student operator =(Student& student)

分配操作员应采用const参考参数。分配运算符还应返回参考,而不是值。

此类也缺少复制构造函数。

在分配运营商中:

this->classList = student.classList;

这是一个简单的指针。对于初学者来说,这是一个内存泄漏。以前的指针(如果有的话)丢失,并且其分配的内存被泄漏。

现在,您有两个使用相同的classList指针的实例。因此,当resetClasses()方法在其中一个类中调用时,它将被删除,并且由于类的另一个实例具有相同的指针,因此现在指向删除内存。

如果有的话,您的分配运算符必须正确删除现有数组,并克隆在实例中持有的数组(如果有)。其中大部分也适用于您必须实现的复制构造函数。

此类也缺少一个破坏者,这将导致另一个内存泄漏。

您遇到了班级的所有这些基本问题。您必须修复所有这些,以使您的班级正常工作。您必须实施适当的复制构造函数,分配运算符和驱动器,该构造器正确克隆,复制和破坏您的班级持有的数据实例。

看来,您尚未学会如何使用容器和智能指针,以及您是否要学习如何正确跟踪分配的内存,避免内存损坏和内存泄漏的方法。这显然是一项重要的学习技能。但是,一旦您弄清楚了所有这些,并且您的班级正常工作,您就可以将指针替换为std::vector,而不再担心它。

您需要创建类列表的副本,否则两个学生对象都会在内存中指向相同位置。

释放这些领域之一将导致另一个领域也被释放。

在您的复制构造函数和分配运算符中,创建一个新对象的新数组,然后将每个元素复制到新对象。