在 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。
- 这样做的正确方法是什么?
- 学生 class 是否遗漏了一些重要的组成部分?
我不能使用 std::vector
或 std::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 违规错误。完成后,导致访问冲突的原始复制问题应该得到解决。
我有一个 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。
- 这样做的正确方法是什么?
- 学生 class 是否遗漏了一些重要的组成部分?
我不能使用 std::vector
或 std::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 违规错误。完成后,导致访问冲突的原始复制问题应该得到解决。