首页 > 解决方案 > 如果我还使用复制构造函数和重载 = 运算符,是否需要析构函数?

问题描述

所以我有这个代码,我有一个类 Student,它是一个带有 *ModuleGrade 类对象的向量。我在 Student 类中有一个析构函数,但在 = 运算符的重载中我也有一个析构函数。我是否需要两次都拥有它,或者我可以将析构函数保留在 Student 类中,它也会在 = 运算符的重载中完成这项工作。我希望我能解释清楚。

编辑: 我知道如果向量没有 * 会更好,但这样做的目的是让我展示我理解 * 和深拷贝构造函数的工作原理。

这是我的代码:

学生.h

 private:
    int studentNumber;
    vector <ModuleGrade*> gradeList;
 public:
    ~Student();
    Student(const Student& student);  // user-defined copy ctor
    Student& operator = (const Student& student);

学生.cpp

Student::~Student() 
{

    int number = gradeList.size();
    for(int i= 0; i<number; i++){
        delete gradeList[i];
    }
} 


Student::Student(const Student &student ) : Person(student) {
    //deep copy constructor
    this->studentNumber=student.studentNumber;
    int size = student.gradeList.size();
    for(int i=0; i <size; i++) {

       // ModuleGrade *m ;
        ModuleGrade *mg = new ModuleGrade(*(student.gradeList[i]));
        gradeList.push_back(mg);
    }

}

Student& Student :: operator = (const Student & student) {
    if (&student == this) return *this;
    Person :: operator=(student);
    studentNumber = student.studentNumber;

    //delete gradeList of this
    //SHOULD I DO THIS IF THERE IS A DESTRUCTOR DECLARED???
    for (unsigned int i=0; i<gradeList.size(); i++){
        delete gradeList[i];
        gradeList.clear();
    }

    //fill this with grades of student
    for(unsigned int i=0; i<student.gradeList.size(); i++) {
        ModuleGrade *m = new ModuleGrade(*(student.gradeList[i]));
        gradeList.push_back(m);

    }

    return *this;
}

标签: c++

解决方案


是的,如果您管理指针,那么您需要确保在分配和销毁时清理指向的对象。

这就是人们经常使用 move 和 swap 来编写赋值运算符的原因:

X& operator=(X const& other){
   X temp(other);
   swap(temp);
   return *this;
}

因为清理然后只需要写在析构函数中。swap只是交换内容,复制构造函数分配新的内容。

使用 move-and-swap 还涵盖了您编写的情况,x=x否则,如果您在尝试从另一个对象复制数据之前破坏了被分配对象指向的数据,则需要在赋值运算符中显式测试该情况目的。

此外,在实际代码中,您应该使用std::unique_ptr或者std::shared_ptr如果您想通过指针保存对象:您永远不必delete手动编写,您也可以经常使用std::make_uniqueorstd::make_shared来代替new


推荐阅读