在 C++ 中增加自定义对象数组的大小

Increasing the size of the custom objects array in c++

我有一个 class 学生和动态创建的学生数组:

class Student{
public:
  void create(){
    system("cls");
    cout << "First name: ";
    cin >> fn;
    cout << "Last name: ";
    cin >> ln;
    cout << "How many subjects? ";
    cin >> sub_number;
    subjects = new string[sub_number];
    for(int i = 0; i < sub_number; i++){
      cout << "Subject name: ";
      cin >> subject[i];
    }
  }

  //This just display the student with a bunch of couts
  friend ostream& operator<<(ostream&, const Student&);

  ~Student(){ delete[] subjects; }
private:
  string fn;
  string ln;
  string* subjects;
  int sub_number;
};

我需要将这个数组的大小增加 1 并向其中添加一个新学生。

当我尝试简单地做到这一点时:

void main(){
   int stu_number = 0;
   cout << "How many students? "
   cin >> stu_number;
   Student* students = new Student[stu_number];

   //creating/updating initial students using user input
   for(int i = 0; i < stu_number; i++){
     students[i].create();
   }

   //displaying all students
   for(int i = 0; i < stu_number; i++){
     cout << students[i];
   }

   //trying to add a student
   add_new_student(students, stu_number);

   //displaying all students again
   for(int i = 0; i < stu_number; i++){
     cout << students[i];
   }
}

add_new_student函数:

void add_new_student(Student* students, int& stu_number){
  Student* temp = new Student[stu_number++];
  for (int i = 0; i < stu_number - 1; i++){
    temp[i] = students[i];
  }
  temp[stu_number - 1].create(); 
  delete[] students;
  students = temp;
}

我收到内存冲突错误和未处理的异常:add_new_student 函数内的访问冲突写入位置 0xABABABAB。

我不能使用 std::vectorstd::list,因为这是学校作业:)

要增加数组的大小,您基本上必须:

  • 新建一个更大的数组
  • 将值从旧的较小数组复制到新的较大数组
  • 删除旧的较小数组

话虽这么说,但如果您可以,我建议您改用 std::vector,因为它具有可以为您调整大小的实用方法。

无论 create 是为 [1] 调用的,默认构造函数肯定有问题[2]您的 Student class:它似乎错过了 create.

中使用的重要元素的初始化
  • [1] 顺便说一句:create 的目的是什么?
  • [2]有默认构造函数吗?使用什么 C++ 标准?

您的问题是由缺少赋值运算符引起的。在 for 循环中的赋值中,有一个 subjects 数组的平面副本,当删除原始 students 数组时,该副本也被删除。在那之后,第一个 Student 对象中有一个所谓的悬挂指针。

assignment operator 负责安全地(并在语义上更正)将所有元素从一个对象复制到另一个对象。

另外: 添加一些跟踪输出以详细了解这里发生的事情会非常有趣(提供信息)。

问题是你的 Student class 没有遵循 "rule of 3":

What is The Rule of Three?

如果您的 class 有一个用户定义的析构函数,那么它还应该提供一个用户定义的复制构造函数和赋值运算符。现在发生的事情是,当执行此行时:

temp[i] = student[i];

您正在调用赋值运算符。但是,您的 Student 对象在分配时只会将指针值从一个对象复制到另一个对象。当调用这些 Student 对象中的任何一个的 destructor 时会发生什么?析构函数将删除相同的指针值两次,因此会出错。

这是您当前 Student class.

的精简版
#include <string>

class Student
{
      std::string* subjects;
      std::string fn;
      std::string ln;
      int sub_number;

   public:
      Student(size_t numSubjects=5) : subjects(new std::string[numSubjects]), 
                                      sub_number(numSubjects){} 

      ~Student() { delete [] subjects; }
};

// Test code
int main()
{
    Student s1(10);
    Student s2 = s1;
    Student s3;
    s3 = s1;
}

如果你运行这个程序,你会看到内存泄漏和双删除错误的问题,如下所示:http://ideone.com/MQhpcK

我所做的只是复制 Student 个对象,问题就出现了。

要解决此问题,您必须在 Student class:

中添加并实现这些功能
      Student(const Student& rhs);  // copy constructor
      Student& operator=(const Student& rhs); // assignment operator

一旦你实现了这些功能,测试上面的程序以确保它确实正确地制作副本,没有内存泄漏和分段 faults/access 违规错误。完成后,导致访问冲突的原始复制问题应该得到解决。