C++ 实例化新类时发生堆栈溢出错误
我有一个“Class”类,它有一个字符串名和一个“Student”对象数组。“学生”班有名字和“成绩”。“等级”类是一个双倍数组 在main类中,我创建了一个Grades对象和一个Student对象。我用它测试了一些功能,所有功能都运行良好:C++ 实例化新类时发生堆栈溢出错误,c++,class,stack-overflow,C++,Class,Stack Overflow,我有一个“Class”类,它有一个字符串名和一个“Student”对象数组。“学生”班有名字和“成绩”。“等级”类是一个双倍数组 在main类中,我创建了一个Grades对象和一个Student对象。我用它测试了一些功能,所有功能都运行良好: int main(){ cout << fixed << setprecision(2); Grades test = Grades ("5 - 90.0 85.0 95.5 77.5 88.0"); c
int main(){
cout << fixed << setprecision(2);
Grades test = Grades ("5 - 90.0 85.0 95.5 77.5 88.0");
cout << test.toString() << endl;
cout << "\nSum = " << test.getSum() << endl;
cout << "Num grades = " << test.getNumGrades() << endl;
cout << "Low grade = " << test.getLowGrade() << endl;
cout << "High grade = " << test.getHighGrade() << endl;
Student stu = Student("Billy Bob", "5 - 90 85 95.5 77.5 88");
cout << stu.toString() << endl;
cout << "\nSum = " << stu.getSum() << endl;
cout << "Average = " << stu.getAverage() << endl;
cout << "Average after dropping low grade = " << stu.getAverageMinusLow() << endl;
cout << "Low grade = " << stu.getLowGrade() << endl;
cout << "High grade = " << stu.getHighGrade() << endl;
}
然后运行程序,它有一个堆栈溢出错误。
“Gradebook.exe中0x0033EAB7处的第一次机会异常:0xC00000FD:堆栈溢出(参数:0x00000000,0x003D2000)。”
如果存在此异常的处理程序,则程序可以安全地继续。
是否因为对象太多,而每个对象都是另一个对象的成员?有没有办法“删除”在这一行之前创建的我的“test”和“stu”对象
以下是我的“类”构造函数供参考:
class Class{
private:
string name;
Student studentList[100];
int numStudents;
public: Class(string className, int numStudents1);
Class();
}
Class:: Class(string className, int numStudents1){
name = className;
numStudents = numStudents1;
}
Class:: Class(){
name = "";
numStudents = 0;
}
出现此错误是因为类对象中的“studentList”学生数组未在构造函数中实例化吗?函数中声明的每个变量都位于堆栈上,函数外部声明的变量都是静态变量并使用
这在某些方面也是不好的,但没有造成堆栈溢出那么严重。这种设计完全是错误的 在
Student
中应该有一个向量或类似的容器来容纳所有的成绩,在Class
中应该有一个类似的容器来容纳所有的学生。你说你的老师不允许你使用vector,这对你的水平没有多大意义,但也许他希望你创建自己的容器类?再说一次,你似乎还没有完全做到这一点,所以这是一种悖论
你的问题是,你在一个班级里有足够的存储空间分配给100名学生,而这100名学生可能有很多分数,因此这个班级可能会变得庞大,太大而无法放在堆栈上,这就是它溢出的原因。这样,班级加上学生再加上成绩就形成了一大块“扁平”的记忆。当你在没有编译器优化的情况下使用这种实例化形式时,它创建的不是一个而是两个对象,只是将后者分配给前者。修复类构造函数(您也应该修复其他构造函数)可能会修复溢出问题,但不会修复您的设计问题
让类
这样的大结构在内存中不是平坦的,这是非常简单且推荐的好做法。将其扁平化实际上更为复杂,但可能有其他优势(如性能或内存效率),并且仍然可以安全地使用动态分配,但在您的情况下,您对一流的效率不感兴趣,但需要理解,因此需要良好的设计
此外,正如评论中提到的,用分数创建学生是错误的,尤其是以字符串形式通过分数。如果这是一个你必须在实践中使用的真正的课程,那么如果成绩还没有出来,你将如何在年初创造出所有成绩的新学生?学生类构造函数应该只为学生传递一个名称,而应该有一个addGrade()
成员函数
那个类对象预分配一个长度为100的静态数组呢?如果你只有3个学生,那么就浪费了97个学生的记忆。如果你需要100多名学生怎么办?你的程序崩溃了。这就是为什么你应该使用一个容器,并且只有你需要的学生数量。我只能假设同样可怕的事情正在学生课堂上发生。这些类型的“技术”通常用于旧的C代码中,这可能是您的老师所困扰的,但肯定不推荐用于现代C++教学。为什么不<代码>类TestCclass(“COMP SCI 1”,3);<代码>?除此之外,您必须显示更多的代码以找出错误所在。您似乎混淆了堆栈和堆实例化。现在,由于您分配的方式,您正在导致不必要的复制操作。另外,当您确定学生数为100时,为什么要通过学生数?使用向量代替,只需要你需要的学生数量。这样一来,学生就不会被放在堆上,这可能是导致溢出的原因。您所做的是创建一个类,然后将其复制到testClass,这是不必要的。但您的实施策略还有其他问题。谢谢@ddriver。这起作用了。我将在C++中看到更多的堆栈和堆分配。我不能使用向量,因为我的老师不允许。否则,我肯定会用它。。。。?堆和静态数据段是不等价的。@milleniumbug很多都是这样的。堆是数据段的一部分(至少wikipedia同意这一点……但你们不应该相信wiki上的一切)。
class Class{
private:
string name;
Student studentList[100];
int numStudents;
public: Class(string className, int numStudents1);
Class();
}
Class:: Class(string className, int numStudents1){
name = className;
numStudents = numStudents1;
}
Class:: Class(){
name = "";
numStudents = 0;
}
Class testClass("Comp Sci 1", 3);
int main(){