C++ vector元素每次输入后全部被覆盖的问题如何修复?
问题修复方案
核心问题原因
- 内存分配错误:你给
name/highscore/password三个指针仅分配了1字节内存,连字符串末尾的结束符\0都无法存储,读入任意长度大于1的字符串都会触发内存越界,属于未定义行为。 - 指针重复复用:所有指针和
player对象都是在循环外仅初始化一次,每次读入的新内容都会覆盖同一块内存空间,vector中存储的都是指向同一块内存的指针,自然所有元素都会同步变成最新输入的值。 - 不必要的堆分配:
vector <char*>* names这种用指针存储vector的写法完全没有必要,直接在栈上声明vector即可,反而会增加内存泄漏风险。 - 输入判断逻辑错误:
while(input.good())的判断会导致最后一行内容重复读入,应该直接将输入操作放到while循环的判断条件中。
推荐修复方案(C++标准写法,无手动内存管理风险)
优先将player类的char*类型成员替换为std::string,无需手动管理内存,从根源避免越界、泄漏、覆盖问题:
// 修改player类定义 class player { public: std::string name; std::string highscore; std::string password; player(std::string n, std::string h, std::string p) : name(std::move(n)), highscore(std::move(h)), password(std::move(p)) {} // 对应的>>运算符重载也修改为直接读入string成员即可 friend std::istream& operator>>(std::istream& in, player& p) { // 按你的csv分隔逻辑读入三个字段到p.name、p.highscore、p.password return in; } }; // 业务代码修改为 std::vector<player> players; std::vector<std::string> names; std::vector<std::string> passwords; std::vector<int> scores; std::ifstream input("user.csv"); std::cout << "Welcome to Champion Yahtzee\n"; std::cout << "Player Name Highest Score\n"; std::cout << "----------- -------------\n"; player tmp; while (input >> tmp) { // 读入成功才执行后续逻辑 players.push_back(tmp); names.push_back(tmp.name); scores.push_back(std::stoi(tmp.highscore)); passwords.push_back(tmp.password); }
保留char*写法的修复方案(不推荐,需自行管理内存避免泄漏)
如果必须使用char*,需要把内存分配逻辑放到循环内部,每次读入前都申请新的内存空间:
std::vector<player*> players; std::vector<char*> names; std::vector<char*> passwords; std::vector<int> scores; std::ifstream input("user.csv"); std::cout << "Welcome to Champion Yahtzee\n"; std::cout << "Player Name Highest Score\n"; std::cout << "----------- -------------\n"; const int BUF_SIZE = 128; // 根据实际字段最大长度调整缓冲区大小 while (true) { // 每次循环申请新的内存 char* name = (char*)malloc(BUF_SIZE * sizeof(char)); char* highscore = (char*)malloc(BUF_SIZE * sizeof(char)); char* password = (char*)malloc(BUF_SIZE * sizeof(char)); player* c = new player(name, highscore, password); if (!(input >> *c)) { // 读入失败释放内存后退出循环 free(name); free(highscore); free(password); delete c; break; } players.emplace_back(c); names.push_back(name); scores.push_back(atoi(highscore)); passwords.push_back(password); } // 注意:程序退出前需要遍历所有vector,逐个free char*、delete player对象,否则会出现内存泄漏
内容的提问来源于stack exchange,提问作者Aurous
相关产品推荐
相关产品推荐

