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

时间:2015-03-25 13:27:54

标签: c++ arrays

我有一个班级学生和动态创建的学生阵列:

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,因为这是学校作业:)

4 个答案:

答案 0 :(得分:5)

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

  • 创建一个更大尺寸的新阵列
  • 将旧较小数组中的值复制到新的较大数组
  • 删除旧的较小数组

话虽如此,如果你能够我建议切换到std::vector,因为它有适用于你的实用程序方法。

答案 1 :(得分:2)

问题是您的Student课程没有遵循3&#34;&#34;规则:

What is The Rule of Three?

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

temp[i] = student[i];

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

以下是您当前Student课程的精简版。

#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类中添加并实现这些功能:

      Student(const Student& rhs);  // copy constructor
      Student& operator=(const Student& rhs); // assignment operator

实现这些功能后,请测试上面的程序,以确保它能够真正正确地制作副本,而不会出现内存泄漏和分段错误/访问冲突错误。完成后,应解决导致访问冲突的原始复制问题。

答案 2 :(得分:1)

您的问题是由缺少的赋值运算符引起的。在for循环中的赋值中,有一个subject数组的平面副本,删除原始student数组时删除它。之后,在第一个Student对象中有一个所谓的悬空指针。

assignment operator可以安全地(并且语义上正确)将所有元素从一个对象复制到另一个对象。

此外:添加一些跟踪输出非常有趣(提供信息),以便详细了解这里发生了什么。

答案 3 :(得分:0)

无论{sup> [1] 调用createStudent类的默认构造函数 [2] 一定有问题:它似乎错过了初始化create中使用的重要元素。


  • [1] BTW:create的目的是什么?
  • [2] 是否有默认构造函数?使用什么C ++标准?