C++中创建带构造函数的类对象数组及添加对象时程序崩溃问题
嘿,我来帮你揪出程序崩溃的根源,咱们一步步拆解问题:
核心崩溃原因:非法内存访问(数组越界)
你的程序崩溃直接来自这段代码:
Student *s4; for(int i = 0; i < 2; i++) { s4=s3; } s4[3].addStd(2,"mary");
这里的问题出在:
s3是一个长度为2的Student数组,它的有效索引只有0和1(数组元素从0开始计数)。- 你让
s4指向s3的首地址后,直接访问s4[3]——这已经超出了数组的合法范围,属于访问非法内存,操作系统会直接终止程序,也就是你看到的崩溃。 - 另外那个循环
for(int i = 0; i < 2; i++) { s4=s3; }完全是多余的,循环两次赋值同一个地址,没有任何实际作用。
修复方案:动态管理学生对象
如果你想添加新的学生,不能直接在固定大小的数组上越界操作,推荐两种更安全的方式:
方式1:使用C++标准库的vector(推荐)
vector可以自动管理动态扩容,不用手动处理内存,代码更简洁安全:
#include <iostream> #include <string> #include <vector> // 新增头文件 using namespace std; class Student { int id; string name; float letter[5]; public: Student(int studentId) : id(studentId), name("ali") { // 改用初始化列表 for (int i = 0;i<5;i++) { letter[i] = 12; } } Student(int studentId, string Sname, float d[5]) : id(studentId), name(Sname) { for (int i = 0; i < 5; i++) { letter[i] = d[i]; } } void updateInfo(int studentId, string Sname) { // 重命名方法,语义更准确 id = studentId; name = Sname; for (int i = 0; i < 5; i++) { letter[i] = 15; } } void PrintStd() { cout << id << "\t" << name << "\t"; for(int i=0;i<5;i++) { cout << letter[i] << "\t"; } cout << endl; } }; int main() { Student S1(1); float dd1[5] = {20,20,20,20,20}; Student S2(2,"jack",dd1); // 用vector存储学生 vector<Student> students; students.emplace_back(1); // 直接构造第一个学生 students.emplace_back(2,"fered",dd1); // 构造第二个学生 // 添加新学生:先构造临时对象,再修改信息 students.emplace_back(0); students.back().updateInfo(3,"mary"); // 修改最后一个学生的信息 // 打印所有学生 cout << "所有学生信息:" << endl; for (auto& student : students) { student.PrintStd(); cout << "*************" << endl; } return 0; }
方式2:手动管理动态数组
如果你想坚持用指针和数组,需要手动重新分配内存、复制旧数据,记得最后释放内存:
// 类定义和之前一致,略去 int main() { float dd1[5] = {20,20,20,20,20}; int currentSize = 2; // 动态分配初始数组 Student *s4 = new Student[currentSize]{Student(1), Student(2,"fered",dd1)}; // 要添加新学生,先扩容数组 int newSize = currentSize + 1; Student *temp = new Student[newSize]; // 复制旧数据 for(int i=0; i<currentSize; i++) { temp[i] = s4[i]; } // 设置新学生信息 temp[2].updateInfo(3,"mary"); // 释放旧内存,更新指针 delete[] s4; s4 = temp; currentSize = newSize; // 打印所有学生 cout << "所有学生信息:" << endl; for(int i=0; i<currentSize; i++) { s4[i].PrintStd(); cout << "*************" << endl; } // 最后记得释放动态分配的内存 delete[] s4; return 0; }
额外优化建议
- 构造函数的参数名
size容易混淆(它实际是学生ID),建议改成studentId,代码可读性更强。 - 尽量用初始化列表初始化类成员变量(像上面修复代码里那样),比在构造函数体内赋值更高效规范。
addStd方法的语义不准确——它是修改当前对象的信息,不是添加新对象,建议改名为updateInfo或者setStudentInfo。
内容的提问来源于stack exchange,提问作者user3115252
相关产品推荐
相关产品推荐

